anathema_widgets/components/
mod.rs

1use std::any::Any;
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut};
4use std::time::Duration;
5
6use anathema_state::{State, StateId, Value as StateValue};
7use anathema_store::slab::Slab;
8use anathema_templates::strings::{StringId, Strings};
9use anathema_templates::{AssocEventMapping, ComponentBlueprintId};
10use anathema_value_resolver::{Attributes, ValueKind};
11use deferred::DeferredComponents;
12use flume::SendError;
13
14use self::events::{Event, KeyEvent, MouseEvent};
15use crate::WidgetId;
16use crate::layout::Viewport;
17use crate::query::Children;
18use crate::widget::Parent;
19
20pub mod deferred;
21pub mod events;
22
23pub type ComponentFn = dyn Fn() -> Box<dyn AnyComponent>;
24pub type StateFn = dyn FnMut() -> Box<dyn State>;
25
26enum ComponentType {
27    Component(Option<Box<dyn AnyComponent>>, Option<Box<dyn State>>),
28    Prototype(Box<ComponentFn>, Box<StateFn>),
29}
30
31/// Store component factories.
32/// This is how components are created.
33pub struct ComponentRegistry(Slab<ComponentBlueprintId, ComponentType>);
34
35impl ComponentRegistry {
36    pub fn new() -> Self {
37        Self(Slab::empty())
38    }
39
40    /// Both `add_component` and `add_prototype` are using `Slab::insert_at`.
41    ///
42    /// This is fine as the component ids are generated at the same time.
43    pub fn add_component<S: State>(&mut self, id: ComponentBlueprintId, component: impl Component + 'static, state: S) {
44        let comp_type = ComponentType::Component(Some(Box::new(component)), Some(Box::new(state)));
45        self.0.insert_at(id, comp_type);
46    }
47
48    pub fn add_prototype<FC, FS, C, S>(&mut self, id: ComponentBlueprintId, proto: FC, mut state: FS)
49    where
50        FC: 'static + Fn() -> C,
51        FS: 'static + FnMut() -> S,
52        C: Component + 'static,
53        S: State + 'static,
54    {
55        let comp_type =
56            ComponentType::Prototype(Box::new(move || Box::new(proto())), Box::new(move || Box::new(state())));
57
58        self.0.insert_at(id, comp_type);
59    }
60
61    /// # Panics
62    ///
63    /// Panics if the component isn't registered.
64    /// This shouldn't happen as the statement eval should catch this.
65    pub fn get(&mut self, id: ComponentBlueprintId) -> Option<(ComponentKind, Box<dyn AnyComponent>, Box<dyn State>)> {
66        match self.0.get_mut(id) {
67            Some(component) => match component {
68                ComponentType::Component(comp, state) => Some((ComponentKind::Instance, comp.take()?, state.take()?)),
69                ComponentType::Prototype(proto, state) => Some((ComponentKind::Prototype, proto(), state())),
70            },
71            None => panic!(),
72        }
73    }
74
75    /// Return a component back to the registry.
76    ///
77    /// # Panics
78    ///
79    /// Panics if the component entry doesn't exist or if the entry is for a prototype.
80    pub fn return_component(
81        &mut self,
82        id: ComponentBlueprintId,
83        current_component: Box<dyn AnyComponent>,
84        current_state: Box<dyn State>,
85    ) {
86        match self.0.get_mut(id) {
87            Some(component) => match component {
88                ComponentType::Component(comp, state) => {
89                    *comp = Some(current_component);
90                    *state = Some(current_state);
91                }
92                ComponentType::Prototype(..) => panic!("trying to return a prototype"),
93            },
94            None => panic!(),
95        }
96    }
97}
98
99#[derive(Debug)]
100pub struct ComponentId<T>(pub(crate) ComponentBlueprintId, pub(crate) PhantomData<T>);
101
102impl<T> From<ComponentBlueprintId> for ComponentId<T> {
103    fn from(value: ComponentBlueprintId) -> Self {
104        Self(value, PhantomData)
105    }
106}
107
108impl<T> Clone for ComponentId<T> {
109    fn clone(&self) -> Self {
110        *self
111    }
112}
113
114impl<T> Copy for ComponentId<T> {}
115
116pub struct ViewMessage {
117    pub(super) payload: Box<dyn Any + Send + Sync>,
118    pub(super) recipient: ComponentBlueprintId,
119}
120
121impl ViewMessage {
122    pub fn recipient(&self) -> ComponentBlueprintId {
123        self.recipient
124    }
125
126    pub fn payload(self) -> Box<dyn Any + Send + Sync> {
127        self.payload
128    }
129}
130
131#[derive(Debug, Clone)]
132pub struct Emitter(pub(crate) flume::Sender<ViewMessage>);
133
134impl From<flume::Sender<ViewMessage>> for Emitter {
135    fn from(value: flume::Sender<ViewMessage>) -> Self {
136        Self(value)
137    }
138}
139
140impl Emitter {
141    pub fn emit<T: 'static + Send + Sync>(
142        &self,
143        component_id: ComponentId<T>,
144        value: T,
145    ) -> Result<(), SendError<ViewMessage>> {
146        let msg = ViewMessage {
147            payload: Box::new(value),
148            recipient: component_id.0,
149        };
150        self.0.send(msg)
151    }
152
153    pub async fn emit_async<T: 'static + Send + Sync>(
154        &self,
155        component_id: ComponentId<T>,
156        value: T,
157    ) -> Result<(), SendError<ViewMessage>> {
158        let msg = ViewMessage {
159            payload: Box::new(value),
160            recipient: component_id.0,
161        };
162        self.0.send_async(msg).await
163    }
164}
165
166pub struct Context<'frame, 'bp, T> {
167    inner: AnyComponentContext<'frame, 'bp>,
168    _p: PhantomData<T>,
169}
170
171impl<'frame, 'bp, T: 'static> Context<'frame, 'bp, T> {
172    pub fn new(inner: AnyComponentContext<'frame, 'bp>) -> Self {
173        Self { inner, _p: PhantomData }
174    }
175
176    /// Publish an event
177    ///
178    /// # Panics
179    ///
180    /// This will panic if the shared value is exclusively borrowed
181    /// at the time of the invocation.
182    pub fn publish<D: 'static>(&mut self, ident: &str, data: D) {
183        // If there is no parent there is no one to emit the event to.
184        let Some(parent) = self.parent else { return };
185
186        let Some(ident_id) = self.inner.strings.lookup(ident) else { return };
187
188        let ids = self.assoc_functions.iter().find(|assoc| assoc.internal == ident_id);
189
190        let Some(assoc_event_map) = ids else { return };
191
192        self.inner.assoc_events.push(
193            self.state_id,
194            parent,
195            *assoc_event_map,
196            self.ident_id,
197            self.sender_id,
198            data,
199        );
200    }
201
202    /// Get a value from the component attributes
203    pub fn attribute(&self, key: &str) -> Option<&ValueKind<'_>> {
204        self.attributes.get(key)
205    }
206
207    /// Send a message to a given component
208    pub fn emit<M: 'static + Send + Sync>(&self, recipient: ComponentId<M>, value: M) {
209        self.emitter
210            .emit(recipient, value)
211            .expect("this will not fail unless the runtime is droped")
212    }
213}
214
215impl<'frame, 'bp, T> Deref for Context<'frame, 'bp, T> {
216    type Target = AnyComponentContext<'frame, 'bp>;
217
218    fn deref(&self) -> &Self::Target {
219        &self.inner
220    }
221}
222
223impl<'frame, 'bp, T> DerefMut for Context<'frame, 'bp, T> {
224    fn deref_mut(&mut self) -> &mut Self::Target {
225        &mut self.inner
226    }
227}
228
229pub struct AnyComponentContext<'frame, 'bp> {
230    parent: Option<Parent>,
231    ident_id: StringId,
232    sender_id: WidgetId,
233    state_id: StateId,
234    assoc_functions: &'frame [AssocEventMapping],
235    assoc_events: &'frame mut AssociatedEvents,
236    pub attributes: &'frame mut Attributes<'bp>,
237    state: Option<&'frame mut StateValue<Box<dyn State>>>,
238    pub emitter: &'frame Emitter,
239    pub viewport: &'frame Viewport,
240    pub strings: &'frame Strings,
241    pub components: &'frame mut DeferredComponents,
242    stop_runtime: &'frame mut bool,
243}
244
245impl<'frame, 'bp> AnyComponentContext<'frame, 'bp> {
246    pub fn new(
247        parent: Option<Parent>,
248        ident_id: StringId,
249        sender_id: WidgetId,
250        state_id: StateId,
251        assoc_functions: &'frame [AssocEventMapping],
252        assoc_events: &'frame mut AssociatedEvents,
253        components: &'frame mut DeferredComponents,
254        attributes: &'frame mut Attributes<'bp>,
255        state: Option<&'frame mut StateValue<Box<dyn State>>>,
256        emitter: &'frame Emitter,
257        viewport: &'frame Viewport,
258        stop_runtime: &'frame mut bool,
259        strings: &'frame Strings,
260    ) -> Self {
261        Self {
262            parent,
263            ident_id,
264            sender_id,
265            state_id,
266            assoc_functions,
267            assoc_events,
268            attributes,
269            components,
270            state,
271            emitter,
272            viewport,
273            strings,
274            stop_runtime,
275        }
276    }
277
278    pub fn parent(&self) -> Option<Parent> {
279        self.parent
280    }
281
282    pub fn stop_runtime(&mut self) {
283        *self.stop_runtime = true;
284    }
285}
286
287pub struct AssociatedEvent {
288    pub state: StateId,
289    pub parent: Parent,
290    pub sender: StringId,
291    pub sender_id: WidgetId,
292    event_map: AssocEventMapping,
293    data: Box<dyn Any>,
294}
295
296impl AssociatedEvent {
297    pub fn to_event<'a>(
298        &'a self,
299        internal: &'a str,
300        external: &'a str,
301        sender: &'a str,
302        sender_id: WidgetId,
303    ) -> UserEvent<'a> {
304        UserEvent {
305            external_ident: external,
306            internal_ident: internal,
307            data: &*self.data,
308            sender,
309            sender_id,
310            stop_propagation: false,
311        }
312    }
313
314    pub fn external(&self) -> StringId {
315        self.event_map.external
316    }
317
318    pub fn internal(&self) -> StringId {
319        self.event_map.internal
320    }
321}
322
323#[derive(Debug, Copy, Clone)]
324pub struct UserEvent<'a> {
325    pub sender: &'a str,
326    pub sender_id: WidgetId,
327    pub external_ident: &'a str,
328    pub internal_ident: &'a str,
329    data: &'a dyn Any,
330    stop_propagation: bool,
331}
332
333impl<'a> UserEvent<'a> {
334    pub fn stop_propagation(&mut self) {
335        self.stop_propagation = true;
336    }
337
338    pub fn name(&self) -> &str {
339        self.external_ident
340    }
341
342    /// Cast the event payload to a specific type
343    ///
344    /// # Panics
345    ///
346    /// This will panic if the type is incorrect
347    pub fn data<T: 'static>(&self) -> &'a T {
348        match self.data.downcast_ref() {
349            Some(data) => data,
350            None => panic!("invalid type when casting event data"),
351        }
352    }
353
354    /// Try to cast the event payload to a specific type
355    pub fn data_checked<T: 'static>(&self) -> Option<&'a T> {
356        self.data.downcast_ref()
357    }
358
359    pub fn should_stop_propagation(&self) -> bool {
360        self.stop_propagation
361    }
362}
363
364// The reason the component can not have access
365// to the children during this event is because the parent is borrowing from the
366// child's state while this is happening.
367pub struct AssociatedEvents {
368    inner: Vec<AssociatedEvent>,
369}
370
371impl AssociatedEvents {
372    pub fn new() -> Self {
373        Self { inner: vec![] }
374    }
375
376    fn push<T: 'static>(
377        &mut self,
378        state: StateId,
379        parent: Parent,
380        assoc_event_map: AssocEventMapping,
381        sender: StringId,
382        sender_id: WidgetId,
383        data: T,
384    ) {
385        self.inner.push(AssociatedEvent {
386            state,
387            parent,
388            sender,
389            sender_id,
390            event_map: assoc_event_map,
391            data: Box::new(data),
392        })
393    }
394
395    pub fn next(&mut self) -> Option<AssociatedEvent> {
396        self.inner.pop()
397    }
398}
399
400pub trait Component: 'static {
401    type State: State;
402    type Message;
403
404    const TICKS: bool = true;
405
406    #[allow(unused_variables, unused_mut)]
407    fn on_key(
408        &mut self,
409        key: KeyEvent,
410        state: &mut Self::State,
411        mut children: Children<'_, '_>,
412        mut context: Context<'_, '_, Self::State>,
413    ) {
414    }
415
416    #[allow(unused_variables, unused_mut)]
417    fn on_mount(
418        &mut self,
419        state: &mut Self::State,
420        mut children: Children<'_, '_>,
421        mut context: Context<'_, '_, Self::State>,
422    ) {
423    }
424
425    #[allow(unused_variables, unused_mut)]
426    fn on_unmount(
427        &mut self,
428        state: &mut Self::State,
429        mut children: Children<'_, '_>,
430        mut context: Context<'_, '_, Self::State>,
431    ) {
432    }
433
434    #[allow(unused_variables, unused_mut)]
435    fn on_blur(
436        &mut self,
437        state: &mut Self::State,
438        mut children: Children<'_, '_>,
439        mut context: Context<'_, '_, Self::State>,
440    ) {
441    }
442
443    #[allow(unused_variables, unused_mut)]
444    fn on_focus(
445        &mut self,
446        state: &mut Self::State,
447        mut children: Children<'_, '_>,
448        mut context: Context<'_, '_, Self::State>,
449    ) {
450    }
451
452    #[allow(unused_variables, unused_mut)]
453    fn on_mouse(
454        &mut self,
455        mouse: MouseEvent,
456        state: &mut Self::State,
457        mut children: Children<'_, '_>,
458        mut context: Context<'_, '_, Self::State>,
459    ) {
460    }
461
462    #[allow(unused_variables, unused_mut)]
463    fn on_tick(
464        &mut self,
465        state: &mut Self::State,
466        mut children: Children<'_, '_>,
467        context: Context<'_, '_, Self::State>,
468        dt: Duration,
469    ) {
470    }
471
472    #[allow(unused_variables, unused_mut)]
473    fn on_message(
474        &mut self,
475        message: Self::Message,
476        state: &mut Self::State,
477        mut children: Children<'_, '_>,
478        mut context: Context<'_, '_, Self::State>,
479    ) {
480    }
481
482    #[allow(unused_variables, unused_mut)]
483    fn on_resize(
484        &mut self,
485        state: &mut Self::State,
486        mut children: Children<'_, '_>,
487        mut context: Context<'_, '_, Self::State>,
488    ) {
489    }
490
491    #[allow(unused_variables, unused_mut)]
492    fn on_event(
493        &mut self,
494        event: &mut UserEvent<'_>,
495        state: &mut Self::State,
496        mut children: Children<'_, '_>,
497        mut context: Context<'_, '_, Self::State>,
498    ) {
499    }
500
501    fn accept_focus(&self) -> bool {
502        true
503    }
504}
505
506impl Component for () {
507    type Message = ();
508    type State = ();
509
510    const TICKS: bool = false;
511
512    fn accept_focus(&self) -> bool {
513        false
514    }
515}
516
517#[derive(Debug)]
518pub enum ComponentKind {
519    Instance,
520    Prototype,
521}
522
523pub trait AnyComponent {
524    fn any_event(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, ev: Event) -> Event;
525
526    fn any_message(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, message: Box<dyn Any>);
527
528    fn any_tick(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, dt: Duration);
529
530    fn any_focus(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
531
532    fn any_blur(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
533
534    fn any_resize(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
535
536    fn any_component_event(
537        &mut self,
538        children: Children<'_, '_>,
539        ctx: AnyComponentContext<'_, '_>,
540        value: &mut UserEvent<'_>,
541    );
542
543    fn any_accept_focus(&self) -> bool;
544
545    fn any_ticks(&self) -> bool;
546}
547
548impl<T> AnyComponent for T
549where
550    T: Component,
551    T: 'static,
552{
553    fn any_event(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, event: Event) -> Event {
554        let mut state = ctx
555            .state
556            .take()
557            .map(|s| s.to_mut_cast::<T::State>())
558            .expect("components always have a state");
559        let context = Context::<T::State>::new(ctx);
560        match event {
561            Event::Blur | Event::Focus => (), // Application focus, not component focus.
562            Event::Key(ev) => self.on_key(ev, &mut *state, children, context),
563            Event::Mouse(ev) => self.on_mouse(ev, &mut *state, children, context),
564            Event::Tick(dt) => self.on_tick(&mut *state, children, context, dt),
565            Event::Resize(_) => self.on_resize(&mut *state, children, context),
566            Event::Mount => self.on_mount(&mut *state, children, context),
567            Event::Unmount => self.on_unmount(&mut *state, children, context),
568            Event::Noop | Event::Stop => (),
569        }
570        event
571    }
572
573    fn any_accept_focus(&self) -> bool {
574        self.accept_focus()
575    }
576
577    fn any_ticks(&self) -> bool {
578        T::TICKS
579    }
580
581    fn any_message(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, message: Box<dyn Any>) {
582        let mut state = ctx
583            .state
584            .take()
585            .map(|s| s.to_mut_cast::<T::State>())
586            .expect("components always have a state");
587        let Ok(message) = message.downcast::<T::Message>() else { return };
588        let context = Context::<T::State>::new(ctx);
589        self.on_message(*message, &mut *state, children, context);
590    }
591
592    fn any_focus(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
593        let mut state = ctx
594            .state
595            .take()
596            .map(|s| s.to_mut_cast::<T::State>())
597            .expect("components always have a state");
598        let context = Context::<T::State>::new(ctx);
599        self.on_focus(&mut *state, children, context);
600    }
601
602    fn any_blur(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
603        let mut state = ctx
604            .state
605            .take()
606            .map(|s| s.to_mut_cast::<T::State>())
607            .expect("components always have a state");
608        let context = Context::<T::State>::new(ctx);
609        self.on_blur(&mut *state, children, context);
610    }
611
612    fn any_tick(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, dt: Duration) {
613        let mut state = ctx
614            .state
615            .take()
616            .map(|s| s.to_mut_cast::<T::State>())
617            .expect("components always have a state");
618        let context = Context::<T::State>::new(ctx);
619        self.on_tick(&mut *state, children, context, dt);
620    }
621
622    fn any_resize(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
623        let mut state = ctx
624            .state
625            .take()
626            .map(|s| s.to_mut_cast::<T::State>())
627            .expect("components always have a state");
628        let context = Context::<T::State>::new(ctx);
629        self.on_resize(&mut *state, children, context);
630    }
631
632    fn any_component_event(
633        &mut self,
634        children: Children<'_, '_>,
635        mut ctx: AnyComponentContext<'_, '_>,
636        event: &mut UserEvent<'_>,
637    ) {
638        let mut state = ctx
639            .state
640            .take()
641            .map(|s| s.to_mut_cast::<T::State>())
642            .expect("components always have a state");
643
644        let context = Context::<T::State>::new(ctx);
645
646        self.on_event(event, &mut *state, children, context);
647    }
648}
649
650impl std::fmt::Debug for dyn AnyComponent {
651    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
652        write!(f, "<dyn AnyComponent>")
653    }
654}