use std::{collections::HashMap, fmt::Debug};
use r3bl_redux::*;
use r3bl_rs_utils_core::*;
use crate::*;
#[derive(Default)]
pub struct ComponentRegistry<S, A>
where
S: Debug + Default + Clone + PartialEq + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
pub components: ComponentRegistryMap<S, A>,
pub has_focus: HasFocus,
}
pub type ComponentRegistryMap<S, A> = HashMap<FlexBoxId, SharedComponent<S, A>>;
mod component_registry_impl {
use super::*;
impl<S, A> ComponentRegistry<S, A>
where
S: Debug + Default + Clone + PartialEq + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
pub fn put(&mut self, id: FlexBoxId, component: SharedComponent<S, A>) {
self.components.insert(id, component);
}
pub fn does_not_contain(&self, id: FlexBoxId) -> bool {
!self.components.contains_key(&id)
}
pub fn contains(&self, id: FlexBoxId) -> bool {
self.components.contains_key(&id)
}
pub fn get(&self, id: FlexBoxId) -> Option<&SharedComponent<S, A>> {
self.components.get(&id)
}
pub fn remove(&mut self, id: FlexBoxId) -> Option<SharedComponent<S, A>> {
self.components.remove(&id)
}
}
impl<S, A> ComponentRegistry<S, A>
where
S: Debug + Default + Clone + PartialEq + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
pub fn get_focused_component_ref(
this: &ComponentRegistry<S, A>,
) -> Option<SharedComponent<S, A>> {
if let Some(ref id) = this.has_focus.get_id() {
ComponentRegistry::get_component_ref_by_id(this, *id)
} else {
None
}
}
pub fn get_component_ref_by_id(
this: &ComponentRegistry<S, A>,
id: FlexBoxId,
) -> Option<SharedComponent<S, A>> {
if let Some(component) = this.get(id) {
return Some(component.clone());
}
None
}
pub async fn reset_component(this: &ComponentRegistry<S, A>, id: FlexBoxId) {
if let Some(it) = ComponentRegistry::get_component_ref_by_id(this, id) {
it.write().await.reset();
}
}
pub async fn reset_focused_component(this: &ComponentRegistry<S, A>) {
if let Some(it) = ComponentRegistry::get_focused_component_ref(this) {
it.write().await.reset();
}
}
pub async fn route_event_to_focused_component(
this: &mut ComponentRegistry<S, A>,
input_event: &InputEvent,
state: &S,
shared_store: &SharedStore<S, A>,
shared_global_data: &SharedGlobalData,
window_size: &Size,
) -> CommonResult<EventPropagation> {
if let Some(it) = ComponentRegistry::get_focused_component_ref(this) {
call_handle_event!(
component_registry: this,
shared_component: it,
input_event: input_event,
state: state,
shared_store: shared_store,
shared_global_data: shared_global_data,
window_size: window_size
)
} else {
Ok(EventPropagation::Propagate)
}
}
}
impl<S, A> Debug for ComponentRegistry<S, A>
where
S: Debug + Default + Clone + PartialEq + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ComponentRegistry")
.field("components", &self.components.keys().enumerate())
.field("has_focus", &self.has_focus)
.finish()
}
}
}
#[macro_export]
macro_rules! call_handle_event {
(
component_registry: $component_registry : expr,
shared_component: $shared_component: expr,
input_event: $input_event: expr,
state: $state: expr,
shared_store: $shared_store: expr,
shared_global_data: $shared_global_data: expr,
window_size: $window_size: expr
) => {{
let result_event_propagation = $shared_component
.write()
.await
.handle_event(
ComponentScopeArgs {
shared_global_data: $shared_global_data,
shared_store: $shared_store,
state: $state,
component_registry: $component_registry,
window_size: $window_size,
},
$input_event,
)
.await?;
return Ok(result_event_propagation);
}};
}