🧑‍💻 Redefine typed and generic component lists

This commit is contained in:
Manuel Cillero 2023-11-13 17:13:14 +01:00
parent f208da1b7b
commit 905b4b1cba
12 changed files with 176 additions and 186 deletions

View file

@ -10,14 +10,14 @@ pub enum FormMethod {
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Form { pub struct Form {
id : OptionId,
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
id : OptionId,
classes : OptionClasses, classes : OptionClasses,
action : OptionString, action : OptionString,
charset : OptionString, charset : OptionString,
method : FormMethod, method : FormMethod,
stuff : ArcComponents, stuff : AnyComponents,
template : String, template : String,
} }
@ -64,6 +64,12 @@ impl ComponentTrait for Form {
impl Form { impl Form {
// Form BUILDER. // Form BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self { pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value; self.weight = value;
@ -76,12 +82,6 @@ impl Form {
self self
} }
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self { pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes); self.classes.alter_value(op, classes);
@ -106,14 +106,15 @@ impl Form {
self self
} }
#[rustfmt::skip]
pub fn with_element(mut self, element: impl ComponentTrait) -> Self { pub fn with_element(mut self, element: impl ComponentTrait) -> Self {
self.stuff.alter(ArcOp::Add(ArcComponent::with(element))); self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(element)));
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_elements(&mut self, op: ArcOp) -> &mut Self { pub fn alter_elements(&mut self, op: ArcAnyOp) -> &mut Self {
self.stuff.alter(op); self.stuff.alter_value(op);
self self
} }
@ -141,7 +142,7 @@ impl Form {
&self.method &self.method
} }
pub fn elements(&self) -> &ArcComponents { pub fn elements(&self) -> &AnyComponents {
&self.stuff &self.stuff
} }

View file

@ -2,8 +2,8 @@ use crate::prelude::*;
use super::Submenu; use super::Submenu;
type Content = TypedComponent<Html>; type Content = ArcTypedComponent<Html>;
type SubmenuItems = TypedComponent<Submenu>; type SubmenuItems = ArcTypedComponent<Submenu>;
#[derive(Default)] #[derive(Default)]
pub enum ElementType { pub enum ElementType {
@ -54,14 +54,14 @@ impl ComponentTrait for Element {
impl Element { impl Element {
pub fn html(content: Html) -> Self { pub fn html(content: Html) -> Self {
Element { Element {
element_type: ElementType::Html(Content::with(content)), element_type: ElementType::Html(Content::new(content)),
..Default::default() ..Default::default()
} }
} }
pub fn submenu(submenu: Submenu) -> Self { pub fn submenu(submenu: Submenu) -> Self {
Element { Element {
element_type: ElementType::Submenu(SubmenuItems::with(submenu)), element_type: ElementType::Submenu(SubmenuItems::new(submenu)),
..Default::default() ..Default::default()
} }
} }

View file

@ -2,15 +2,13 @@ use crate::prelude::*;
use super::Element; use super::Element;
type Elements = TypedComponents<Element>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Group { pub struct Group {
id : OptionId,
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
id : OptionId, elements : TypedComponents<Element>,
elements : Elements,
} }
impl_handle!(COMPONENT_BASE_MENU_GROUP for Group); impl_handle!(COMPONENT_BASE_MENU_GROUP for Group);
@ -44,6 +42,12 @@ impl ComponentTrait for Group {
impl Group { impl Group {
// Group BUILDER. // Group BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self { pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value; self.weight = value;
@ -56,27 +60,21 @@ impl Group {
self self
} }
#[fn_builder] #[rustfmt::skip]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
pub fn add_element(mut self, element: Element) -> Self { pub fn add_element(mut self, element: Element) -> Self {
self.elements self.elements.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(element)));
.alter(TypedOp::Add(TypedComponent::with(element)));
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_elements(&mut self, op: TypedOp<Element>) -> &mut Self { pub fn alter_elements(&mut self, op: ArcTypedOp<Element>) -> &mut Self {
self.elements.alter(op); self.elements.alter_value(op);
self self
} }
// Group GETTERS. // Group GETTERS.
pub fn elements(&self) -> &Elements { pub fn elements(&self) -> &TypedComponents<Element> {
&self.elements &self.elements
} }
} }

View file

@ -3,9 +3,9 @@ use crate::prelude::*;
use super::{Megamenu, Submenu}; use super::{Megamenu, Submenu};
type Label = L10n; type Label = L10n;
type Content = TypedComponent<Html>; type Content = ArcTypedComponent<Html>;
type SubmenuItems = TypedComponent<Submenu>; type SubmenuItems = ArcTypedComponent<Submenu>;
type MegamenuGroups = TypedComponent<Megamenu>; type MegamenuGroups = ArcTypedComponent<Megamenu>;
#[derive(Default)] #[derive(Default)]
pub enum ItemType { pub enum ItemType {
@ -123,21 +123,21 @@ impl Item {
pub fn html(content: Html) -> Self { pub fn html(content: Html) -> Self {
Item { Item {
item_type: ItemType::Html(Content::with(content)), item_type: ItemType::Html(Content::new(content)),
..Default::default() ..Default::default()
} }
} }
pub fn submenu(label: L10n, submenu: Submenu) -> Self { pub fn submenu(label: L10n, submenu: Submenu) -> Self {
Item { Item {
item_type: ItemType::Submenu(label, SubmenuItems::with(submenu)), item_type: ItemType::Submenu(label, SubmenuItems::new(submenu)),
..Default::default() ..Default::default()
} }
} }
pub fn megamenu(label: L10n, megamenu: Megamenu) -> Self { pub fn megamenu(label: L10n, megamenu: Megamenu) -> Self {
Item { Item {
item_type: ItemType::Megamenu(label, MegamenuGroups::with(megamenu)), item_type: ItemType::Megamenu(label, MegamenuGroups::new(megamenu)),
..Default::default() ..Default::default()
} }
} }

View file

@ -2,15 +2,13 @@ use crate::prelude::*;
use super::Group; use super::Group;
type Groups = TypedComponents<Group>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Megamenu { pub struct Megamenu {
id : OptionId,
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
id : OptionId, groups : TypedComponents<Group>,
groups : Groups,
} }
impl_handle!(COMPONENT_BASE_MENU_MEGAMENU for Megamenu); impl_handle!(COMPONENT_BASE_MENU_MEGAMENU for Megamenu);
@ -44,6 +42,12 @@ impl ComponentTrait for Megamenu {
impl Megamenu { impl Megamenu {
// Megamenu BUILDER. // Megamenu BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self { pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value; self.weight = value;
@ -56,26 +60,21 @@ impl Megamenu {
self self
} }
#[fn_builder] #[rustfmt::skip]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
pub fn add_group(mut self, group: Group) -> Self { pub fn add_group(mut self, group: Group) -> Self {
self.groups.alter(TypedOp::Add(TypedComponent::with(group))); self.groups.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(group)));
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_groups(&mut self, op: TypedOp<Group>) -> &mut Self { pub fn alter_groups(&mut self, op: ArcTypedOp<Group>) -> &mut Self {
self.groups.alter(op); self.groups.alter_value(op);
self self
} }
// Megamenu GETTERS. // Megamenu GETTERS.
pub fn groups(&self) -> &Groups { pub fn groups(&self) -> &TypedComponents<Group> {
&self.groups &self.groups
} }
} }

View file

@ -5,9 +5,9 @@ use super::Item;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Menu { pub struct Menu {
id : OptionId,
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
id : OptionId,
items : TypedComponents<Item>, items : TypedComponents<Item>,
} }
@ -70,6 +70,12 @@ impl ComponentTrait for Menu {
impl Menu { impl Menu {
// Menu BUILDER. // Menu BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self { pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value; self.weight = value;
@ -82,20 +88,15 @@ impl Menu {
self self
} }
#[fn_builder] #[rustfmt::skip]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
pub fn add_item(mut self, item: Item) -> Self { pub fn add_item(mut self, item: Item) -> Self {
self.items.alter(TypedOp::Add(TypedComponent::with(item))); self.items.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(item)));
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_items(&mut self, op: TypedOp<Item>) -> &mut Self { pub fn alter_items(&mut self, op: ArcTypedOp<Item>) -> &mut Self {
self.items.alter(op); self.items.alter_value(op);
self self
} }

View file

@ -2,16 +2,14 @@ use crate::prelude::*;
use super::Item; use super::Item;
type Items = TypedComponents<Item>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Submenu { pub struct Submenu {
id : OptionId,
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
id : OptionId,
title : OptionTranslated, title : OptionTranslated,
items : Items, items : TypedComponents<Item>,
} }
impl_handle!(COMPONENT_BASE_MENU_SUBMENU for Submenu); impl_handle!(COMPONENT_BASE_MENU_SUBMENU for Submenu);
@ -50,6 +48,12 @@ impl ComponentTrait for Submenu {
impl Submenu { impl Submenu {
// Submenu BUILDER. // Submenu BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self { pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value; self.weight = value;
@ -62,26 +66,21 @@ impl Submenu {
self self
} }
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder] #[fn_builder]
pub fn alter_title(&mut self, title: L10n) -> &mut Self { pub fn alter_title(&mut self, title: L10n) -> &mut Self {
self.title.alter_value(title); self.title.alter_value(title);
self self
} }
#[rustfmt::skip]
pub fn add_item(mut self, item: Item) -> Self { pub fn add_item(mut self, item: Item) -> Self {
self.items.alter(TypedOp::Add(TypedComponent::with(item))); self.items.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(item)));
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_items(&mut self, op: TypedOp<Item>) -> &mut Self { pub fn alter_items(&mut self, op: ArcTypedOp<Item>) -> &mut Self {
self.items.alter(op); self.items.alter_value(op);
self self
} }
@ -91,7 +90,7 @@ impl Submenu {
&self.title &self.title
} }
pub fn items(&self) -> &Items { pub fn items(&self) -> &TypedComponents<Item> {
&self.items &self.items
} }
} }

View file

@ -8,8 +8,10 @@ pub use renderable::{FnIsRenderable, Renderable};
mod definition; mod definition;
pub use definition::{component_as_mut, component_as_ref, ComponentBase, ComponentTrait}; pub use definition::{component_as_mut, component_as_ref, ComponentBase, ComponentTrait};
mod arc; mod arc_any;
pub use arc::{ArcComponent, ArcComponents, ArcOp}; pub use arc_any::AnyComponents;
pub use arc_any::{ArcAnyComponent, ArcAnyOp};
mod typed; mod arc_typed;
pub use typed::{TypedComponent, TypedComponents, TypedOp}; pub use arc_typed::TypedComponents;
pub use arc_typed::{ArcTypedComponent, ArcTypedOp};

View file

@ -1,6 +1,6 @@
use crate::core::component::{ComponentTrait, Context}; use crate::core::component::{ComponentTrait, Context};
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{impl_handle, Handle, Weight}; use crate::{fn_builder, impl_handle, Handle, Weight};
use std::sync::{Arc, RwLock, RwLockReadGuard}; use std::sync::{Arc, RwLock, RwLockReadGuard};
@ -16,30 +16,26 @@ impl ComponentTrait for ComponentNull {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct ArcComponent(Arc<RwLock<dyn ComponentTrait>>); pub struct ArcAnyComponent(Arc<RwLock<dyn ComponentTrait>>);
impl Default for ArcComponent { impl Default for ArcAnyComponent {
fn default() -> Self { fn default() -> Self {
ArcComponent(Arc::new(RwLock::new(ComponentNull))) ArcAnyComponent(Arc::new(RwLock::new(ComponentNull)))
} }
} }
impl ArcComponent { impl ArcAnyComponent {
pub fn new() -> Self { pub fn new(component: impl ComponentTrait) -> Self {
ArcComponent::default() ArcAnyComponent(Arc::new(RwLock::new(component)))
} }
pub fn with(component: impl ComponentTrait) -> Self { // ArcAnyComponent BUILDER.
ArcComponent(Arc::new(RwLock::new(component)))
}
// ArcComponent BUILDER.
pub fn set(&mut self, component: impl ComponentTrait) { pub fn set(&mut self, component: impl ComponentTrait) {
self.0 = Arc::new(RwLock::new(component)); self.0 = Arc::new(RwLock::new(component));
} }
// ArcComponent GETTERS. // ArcAnyComponent GETTERS.
pub fn get(&self) -> RwLockReadGuard<'_, dyn ComponentTrait> { pub fn get(&self) -> RwLockReadGuard<'_, dyn ComponentTrait> {
self.0.read().unwrap() self.0.read().unwrap()
@ -57,69 +53,66 @@ impl ArcComponent {
self.0.read().unwrap().weight() self.0.read().unwrap().weight()
} }
// ArcComponent RENDER. // ArcAnyComponent RENDER.
pub fn render(&self, cx: &mut Context) -> Markup { pub fn render(&self, cx: &mut Context) -> Markup {
self.0.write().unwrap().render(cx) self.0.write().unwrap().render(cx)
} }
} }
pub enum ArcOp { // *************************************************************************************************
Add(ArcComponent),
AddAfterId(&'static str, ArcComponent), pub enum ArcAnyOp {
AddBeforeId(&'static str, ArcComponent), Add(ArcAnyComponent),
AddFirst(ArcComponent), AddAfterId(&'static str, ArcAnyComponent),
AddBeforeId(&'static str, ArcAnyComponent),
AddFirst(ArcAnyComponent),
RemoveById(&'static str), RemoveById(&'static str),
ReplaceById(&'static str, ArcComponent), ReplaceById(&'static str, ArcAnyComponent),
Reset, Reset,
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct ArcComponents(Vec<ArcComponent>); pub struct AnyComponents(Vec<ArcAnyComponent>);
impl ArcComponents { impl AnyComponents {
pub fn new() -> Self { pub fn new(arc: ArcAnyComponent) -> Self {
ArcComponents::default() AnyComponents::default().with_value(ArcAnyOp::Add(arc))
} }
pub fn with(arc: ArcComponent) -> Self { pub(crate) fn merge(mixes: &[Option<&AnyComponents>]) -> Self {
let mut components = ArcComponents::new(); let mut opt = AnyComponents::default();
components.alter(ArcOp::Add(arc));
components
}
pub(crate) fn merge(mixes: &[Option<&ArcComponents>]) -> Self {
let mut components = ArcComponents::default();
for m in mixes.iter().flatten() { for m in mixes.iter().flatten() {
components.0.append(&mut m.0.clone()); opt.0.append(&mut m.0.clone());
} }
components opt
} }
// ArcComponents BUILDER. // AnyComponents BUILDER.
pub fn alter(&mut self, op: ArcOp) -> &mut Self { #[fn_builder]
pub fn alter_value(&mut self, op: ArcAnyOp) -> &mut Self {
match op { match op {
ArcOp::Add(arc) => self.0.push(arc), ArcAnyOp::Add(arc) => self.0.push(arc),
ArcOp::AddAfterId(id, arc) => { ArcAnyOp::AddAfterId(id, arc) => {
match self.0.iter().position(|c| c.id().as_deref() == Some(id)) { match self.0.iter().position(|c| c.id().as_deref() == Some(id)) {
Some(index) => self.0.insert(index + 1, arc), Some(index) => self.0.insert(index + 1, arc),
_ => self.0.push(arc), _ => self.0.push(arc),
} }
} }
ArcOp::AddBeforeId(id, arc) => { ArcAnyOp::AddBeforeId(id, arc) => {
match self.0.iter().position(|c| c.id().as_deref() == Some(id)) { match self.0.iter().position(|c| c.id().as_deref() == Some(id)) {
Some(index) => self.0.insert(index, arc), Some(index) => self.0.insert(index, arc),
_ => self.0.insert(0, arc), _ => self.0.insert(0, arc),
} }
} }
ArcOp::AddFirst(arc) => self.0.insert(0, arc), ArcAnyOp::AddFirst(arc) => self.0.insert(0, arc),
ArcOp::RemoveById(id) => { ArcAnyOp::RemoveById(id) => {
if let Some(index) = self.0.iter().position(|c| c.id().as_deref() == Some(id)) { if let Some(index) = self.0.iter().position(|c| c.id().as_deref() == Some(id)) {
self.0.remove(index); self.0.remove(index);
} }
} }
ArcOp::ReplaceById(id, arc) => { ArcAnyOp::ReplaceById(id, arc) => {
for c in self.0.iter_mut() { for c in self.0.iter_mut() {
if c.id().as_deref() == Some(id) { if c.id().as_deref() == Some(id) {
*c = arc; *c = arc;
@ -127,26 +120,30 @@ impl ArcComponents {
} }
} }
} }
ArcOp::Reset => self.0.clear(), ArcAnyOp::Reset => self.0.clear(),
} }
self self
} }
// ArcComponents GETTERS. // AnyComponents GETTERS.
pub fn get_by_id(&self, id: &'static str) -> Option<&ArcComponent> { pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn get_by_id(&self, id: &'static str) -> Option<&ArcAnyComponent> {
self.0.iter().find(|&c| c.id().as_deref() == Some(id)) self.0.iter().find(|&c| c.id().as_deref() == Some(id))
} }
pub fn iter_by_id(&self, id: &'static str) -> impl Iterator<Item = &ArcComponent> { pub fn iter_by_id(&self, id: &'static str) -> impl Iterator<Item = &ArcAnyComponent> {
self.0.iter().filter(|&c| c.id().as_deref() == Some(id)) self.0.iter().filter(|&c| c.id().as_deref() == Some(id))
} }
pub fn iter_by_handle(&self, handle: Handle) -> impl Iterator<Item = &ArcComponent> { pub fn iter_by_handle(&self, handle: Handle) -> impl Iterator<Item = &ArcAnyComponent> {
self.0.iter().filter(move |&c| c.handle() == handle) self.0.iter().filter(move |&c| c.handle() == handle)
} }
// ArcComponents RENDER. // AnyComponents RENDER.
pub fn render(&self, cx: &mut Context) -> Markup { pub fn render(&self, cx: &mut Context) -> Markup {
let mut components = self.0.clone(); let mut components = self.0.clone();

View file

@ -1,34 +1,30 @@
use crate::core::component::{ComponentTrait, Context}; use crate::core::component::{ComponentTrait, Context};
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{Handle, Weight}; use crate::{fn_builder, Handle, Weight};
use std::sync::{Arc, RwLock, RwLockReadGuard}; use std::sync::{Arc, RwLock, RwLockReadGuard};
#[derive(Default)] #[derive(Default)]
pub struct TypedComponent<T: ComponentTrait + Default>(Arc<RwLock<T>>); pub struct ArcTypedComponent<T: ComponentTrait>(Arc<RwLock<T>>);
impl<T: ComponentTrait + Default> Clone for TypedComponent<T> { impl<T: ComponentTrait> Clone for ArcTypedComponent<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self(self.0.clone()) Self(self.0.clone())
} }
} }
impl<T: ComponentTrait + Default> TypedComponent<T> { impl<T: ComponentTrait> ArcTypedComponent<T> {
pub fn new() -> Self { pub fn new(component: T) -> Self {
TypedComponent::<T>::default() ArcTypedComponent(Arc::new(RwLock::new(component)))
} }
pub fn with(component: T) -> Self { // ArcTypedComponent BUILDER.
TypedComponent(Arc::new(RwLock::new(component)))
}
// TypedComponent BUILDER.
pub fn set(&mut self, component: T) { pub fn set(&mut self, component: T) {
self.0 = Arc::new(RwLock::new(component)); self.0 = Arc::new(RwLock::new(component));
} }
// TypedComponent GETTERS. // ArcTypedComponent GETTERS.
pub fn get(&self) -> RwLockReadGuard<'_, T> { pub fn get(&self) -> RwLockReadGuard<'_, T> {
self.0.read().unwrap() self.0.read().unwrap()
@ -46,61 +42,58 @@ impl<T: ComponentTrait + Default> TypedComponent<T> {
self.0.read().unwrap().weight() self.0.read().unwrap().weight()
} }
// TypedComponent RENDER. // ArcTypedComponent RENDER.
pub fn render(&self, cx: &mut Context) -> Markup { pub fn render(&self, cx: &mut Context) -> Markup {
self.0.write().unwrap().render(cx) self.0.write().unwrap().render(cx)
} }
} }
pub enum TypedOp<T: ComponentTrait + Default> { // *************************************************************************************************
Add(TypedComponent<T>),
AddAfterId(&'static str, TypedComponent<T>), pub enum ArcTypedOp<T: ComponentTrait + Default> {
AddBeforeId(&'static str, TypedComponent<T>), Add(ArcTypedComponent<T>),
AddFirst(TypedComponent<T>), AddAfterId(&'static str, ArcTypedComponent<T>),
AddBeforeId(&'static str, ArcTypedComponent<T>),
AddFirst(ArcTypedComponent<T>),
RemoveById(&'static str), RemoveById(&'static str),
ReplaceById(&'static str, TypedComponent<T>), ReplaceById(&'static str, ArcTypedComponent<T>),
Reset, Reset,
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct TypedComponents<T: ComponentTrait + Default>(Vec<TypedComponent<T>>); pub struct TypedComponents<T: ComponentTrait + Default>(Vec<ArcTypedComponent<T>>);
impl<T: ComponentTrait + Default> TypedComponents<T> { impl<T: ComponentTrait + Default> TypedComponents<T> {
pub fn new() -> Self { pub fn new(arc: ArcTypedComponent<T>) -> Self {
TypedComponents::<T>::default() TypedComponents::default().with_value(ArcTypedOp::Add(arc))
}
pub fn with(one: TypedComponent<T>) -> Self {
let mut components = TypedComponents::new();
components.alter(TypedOp::Add(one));
components
} }
// TypedComponents BUILDER. // TypedComponents BUILDER.
pub fn alter(&mut self, op: TypedOp<T>) -> &mut Self { #[fn_builder]
pub fn alter_value(&mut self, op: ArcTypedOp<T>) -> &mut Self {
match op { match op {
TypedOp::Add(one) => self.0.push(one), ArcTypedOp::Add(one) => self.0.push(one),
TypedOp::AddAfterId(id, one) => { ArcTypedOp::AddAfterId(id, one) => {
match self.0.iter().position(|c| c.id().as_deref() == Some(id)) { match self.0.iter().position(|c| c.id().as_deref() == Some(id)) {
Some(index) => self.0.insert(index + 1, one), Some(index) => self.0.insert(index + 1, one),
_ => self.0.push(one), _ => self.0.push(one),
} }
} }
TypedOp::AddBeforeId(id, one) => { ArcTypedOp::AddBeforeId(id, one) => {
match self.0.iter().position(|c| c.id().as_deref() == Some(id)) { match self.0.iter().position(|c| c.id().as_deref() == Some(id)) {
Some(index) => self.0.insert(index, one), Some(index) => self.0.insert(index, one),
_ => self.0.insert(0, one), _ => self.0.insert(0, one),
} }
} }
TypedOp::AddFirst(one) => self.0.insert(0, one), ArcTypedOp::AddFirst(one) => self.0.insert(0, one),
TypedOp::RemoveById(id) => { ArcTypedOp::RemoveById(id) => {
if let Some(index) = self.0.iter().position(|c| c.id().as_deref() == Some(id)) { if let Some(index) = self.0.iter().position(|c| c.id().as_deref() == Some(id)) {
self.0.remove(index); self.0.remove(index);
} }
} }
TypedOp::ReplaceById(id, one) => { ArcTypedOp::ReplaceById(id, one) => {
for c in self.0.iter_mut() { for c in self.0.iter_mut() {
if c.id().as_deref() == Some(id) { if c.id().as_deref() == Some(id) {
*c = one; *c = one;
@ -108,22 +101,26 @@ impl<T: ComponentTrait + Default> TypedComponents<T> {
} }
} }
} }
TypedOp::Reset => self.0.clear(), ArcTypedOp::Reset => self.0.clear(),
} }
self self
} }
// TypedComponents GETTERS. // TypedComponents GETTERS.
pub fn get_by_id(&self, id: &'static str) -> Option<&TypedComponent<T>> { pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn get_by_id(&self, id: &'static str) -> Option<&ArcTypedComponent<T>> {
self.0.iter().find(|&c| c.id().as_deref() == Some(id)) self.0.iter().find(|&c| c.id().as_deref() == Some(id))
} }
pub fn iter_by_id(&self, id: &'static str) -> impl Iterator<Item = &TypedComponent<T>> { pub fn iter_by_id(&self, id: &'static str) -> impl Iterator<Item = &ArcTypedComponent<T>> {
self.0.iter().filter(|&c| c.id().as_deref() == Some(id)) self.0.iter().filter(|&c| c.id().as_deref() == Some(id))
} }
pub fn iter_by_handle(&self, handle: Handle) -> impl Iterator<Item = &TypedComponent<T>> { pub fn iter_by_handle(&self, handle: Handle) -> impl Iterator<Item = &ArcTypedComponent<T>> {
self.0.iter().filter(move |&c| c.handle() == handle) self.0.iter().filter(move |&c| c.handle() == handle)
} }

View file

@ -1,4 +1,4 @@
use crate::core::component::{ArcComponent, ArcComponents, ArcOp}; use crate::core::component::{AnyComponents, ArcAnyComponent, ArcAnyOp};
use crate::core::theme::ThemeRef; use crate::core::theme::ThemeRef;
use crate::{Handle, LazyStatic}; use crate::{Handle, LazyStatic};
@ -9,36 +9,32 @@ static THEME_REGIONS: LazyStatic<RwLock<HashMap<Handle, ComponentsRegions>>> =
LazyStatic::new(|| RwLock::new(HashMap::new())); LazyStatic::new(|| RwLock::new(HashMap::new()));
static COMMON_REGIONS: LazyStatic<RwLock<ComponentsRegions>> = static COMMON_REGIONS: LazyStatic<RwLock<ComponentsRegions>> =
LazyStatic::new(|| RwLock::new(ComponentsRegions::new())); LazyStatic::new(|| RwLock::new(ComponentsRegions::default()));
#[derive(Default)] #[derive(Default)]
pub struct ComponentsRegions(HashMap<&'static str, ArcComponents>); pub struct ComponentsRegions(HashMap<&'static str, AnyComponents>);
impl ComponentsRegions { impl ComponentsRegions {
pub fn new() -> Self { pub fn new(region: &'static str, arc: ArcAnyComponent) -> Self {
ComponentsRegions::default() let mut regions = ComponentsRegions::default();
}
pub fn with(region: &'static str, arc: ArcComponent) -> Self {
let mut regions = ComponentsRegions::new();
regions.add_in(region, arc); regions.add_in(region, arc);
regions regions
} }
pub fn add_in(&mut self, region: &'static str, arc: ArcComponent) { pub fn add_in(&mut self, region: &'static str, arc: ArcAnyComponent) {
if let Some(region) = self.0.get_mut(region) { if let Some(region) = self.0.get_mut(region) {
region.alter(ArcOp::Add(arc)); region.alter_value(ArcAnyOp::Add(arc));
} else { } else {
self.0.insert(region, ArcComponents::with(arc)); self.0.insert(region, AnyComponents::new(arc));
} }
} }
pub fn get_components(&self, theme: ThemeRef, region: &str) -> ArcComponents { pub fn get_components(&self, theme: ThemeRef, region: &str) -> AnyComponents {
let common = COMMON_REGIONS.read().unwrap(); let common = COMMON_REGIONS.read().unwrap();
if let Some(hm) = THEME_REGIONS.read().unwrap().get(&theme.handle()) { if let Some(hm) = THEME_REGIONS.read().unwrap().get(&theme.handle()) {
ArcComponents::merge(&[common.0.get(region), self.0.get(region), hm.0.get(region)]) AnyComponents::merge(&[common.0.get(region), self.0.get(region), hm.0.get(region)])
} else { } else {
ArcComponents::merge(&[common.0.get(region), self.0.get(region)]) AnyComponents::merge(&[common.0.get(region), self.0.get(region)])
} }
} }
} }
@ -48,7 +44,7 @@ pub enum Region {
OfTheme(ThemeRef, &'static str), OfTheme(ThemeRef, &'static str),
} }
pub fn add_component_in(region: Region, arc: ArcComponent) { pub fn add_component_in(region: Region, arc: ArcAnyComponent) {
match region { match region {
Region::Named(name) => { Region::Named(name) => {
COMMON_REGIONS.write().unwrap().add_in(name, arc); COMMON_REGIONS.write().unwrap().add_in(name, arc);
@ -58,7 +54,7 @@ pub fn add_component_in(region: Region, arc: ArcComponent) {
if let Some(hm) = regions.get_mut(&theme.handle()) { if let Some(hm) = regions.get_mut(&theme.handle()) {
hm.add_in(region, arc); hm.add_in(region, arc);
} else { } else {
regions.insert(theme.handle(), ComponentsRegions::with(region, arc)); regions.insert(theme.handle(), ComponentsRegions::new(region, arc));
} }
} }
} }

View file

@ -1,5 +1,5 @@
use crate::base::action; use crate::base::action;
use crate::core::component::{ArcComponent, ArcComponents as RegionComponents, ComponentTrait}; use crate::core::component::{AnyComponents, ArcAnyComponent, ComponentTrait};
use crate::core::component::{Context, ContextOp}; use crate::core::component::{Context, ContextOp};
use crate::core::theme::ComponentsRegions; use crate::core::theme::ComponentsRegions;
use crate::html::{html, Markup, DOCTYPE}; use crate::html::{html, Markup, DOCTYPE};
@ -95,7 +95,7 @@ impl Page {
#[fn_builder] #[fn_builder]
pub fn alter_in(&mut self, region: &'static str, component: impl ComponentTrait) -> &mut Self { pub fn alter_in(&mut self, region: &'static str, component: impl ComponentTrait) -> &mut Self {
self.regions.add_in(region, ArcComponent::with(component)); self.regions.add_in(region, ArcAnyComponent::new(component));
self self
} }
@ -139,7 +139,7 @@ impl Page {
&self.skip_to &self.skip_to
} }
pub fn components_in(&self, region: &str) -> RegionComponents { pub fn components_in(&self, region: &str) -> AnyComponents {
self.regions.get_components(self.context.theme(), region) self.regions.get_components(self.context.theme(), region)
} }