Añade alteración de componentes antes del render

Los componentes implementan a la vez el paradigma "builder" y la
modificación por "setters" para poder ser modificados durante la
creación de la página o alterados antes de ser renderizados.
This commit is contained in:
Manuel Cillero 2022-04-09 18:40:44 +02:00
parent e11b36f7ed
commit ba4cc982be
22 changed files with 872 additions and 412 deletions

View file

@ -13,12 +13,12 @@ pub struct Block {
impl PageComponent for Block { impl PageComponent for Block {
fn new() -> Self { fn new() -> Self {
Block { Block {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
components: PageContainer::new(), components: PageContainer::new(),
title : OptAttr::none(), title : OptAttr::new(),
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("block"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -34,7 +34,7 @@ impl PageComponent for Block {
fn default_render(&self, assets: &mut PageAssets) -> Markup { fn default_render(&self, assets: &mut PageAssets) -> Markup {
let id = assets.serial_id(self.name(), self.id()); let id = assets.serial_id(self.name(), self.id());
html! { html! {
div id=(id) class=[self.classes("block")] { div id=(id) class=[self.classes()] {
@match self.title() { @match self.title() {
Some(title) => h2 class="block-title" { (title) }, Some(title) => h2 class="block-title" { (title) },
None => {} None => {}
@ -63,36 +63,63 @@ impl Block {
// Block BUILDER. // Block BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_title(mut self, title: &str) -> Self { pub fn with_title(mut self, title: &str) -> Self {
self.title.with_value(title); self.alter_title(title);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self
}
pub fn add_classes(mut self, classes: &str) -> Self {
self.classes.add_classes(classes);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Block ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_title(&mut self, title: &str) -> &mut Self {
self.title.with_value(title);
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -107,15 +134,11 @@ impl Block {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -10,7 +10,7 @@ pub struct Chunck {
impl PageComponent for Chunck { impl PageComponent for Chunck {
fn new() -> Self { fn new() -> Self {
Chunck { Chunck {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
html : html! {}, html : html! {},
template : "default".to_owned(), template : "default".to_owned(),
@ -32,24 +32,49 @@ impl PageComponent for Chunck {
impl Chunck { impl Chunck {
pub fn with(html: Markup) -> Self { pub fn with(html: Markup) -> Self {
let mut chunck = Chunck::new(); Chunck::new().with_html(html)
chunck.html = html;
chunck
} }
// Chunck BUILDER. // Chunck BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self
}
pub fn with_html(mut self, html: Markup) -> Self {
self.alter_html(html);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Chunck ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html = html;
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -64,7 +89,3 @@ impl Chunck {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -3,25 +3,27 @@ use crate::prelude::*;
pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub enum ContainerType { Header, Footer, Main, Section, Wrapper }
pub struct Container { pub struct Container {
renderable: fn() -> bool, renderable : fn() -> bool,
weight : i8, weight : i8,
components: PageContainer, components : PageContainer,
container : ContainerType, container : ContainerType,
id : OptIden, id : OptIden,
classes : Classes, classes : Classes,
template : String, inner_classes: Classes,
template : String,
} }
impl PageComponent for Container { impl PageComponent for Container {
fn new() -> Self { fn new() -> Self {
Container { Container {
renderable: always, renderable : render_always,
weight : 0, weight : 0,
components: PageContainer::new(), components : PageContainer::new(),
container : ContainerType::Wrapper, container : ContainerType::Wrapper,
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("container"),
template : "default".to_owned(), inner_classes: Classes::new_with_default("container"),
template : "default".to_owned(),
} }
} }
@ -36,35 +38,35 @@ impl PageComponent for Container {
fn default_render(&self, assets: &mut PageAssets) -> Markup { fn default_render(&self, assets: &mut PageAssets) -> Markup {
match self.container_type() { match self.container_type() {
ContainerType::Header => html! { ContainerType::Header => html! {
header id=[self.id()] class=[self.classes("header")] { header id=[self.id()] class=[self.classes()] {
div class="container" { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(assets))
} }
} }
}, },
ContainerType::Footer => html! { ContainerType::Footer => html! {
footer id=[self.id()] class=[self.classes("footer")] { footer id=[self.id()] class=[self.classes()] {
div class="container" { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(assets))
} }
} }
}, },
ContainerType::Main => html! { ContainerType::Main => html! {
main id=[self.id()] class=[self.classes("main")] { main id=[self.id()] class=[self.classes()] {
div class="container" { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(assets))
} }
} }
}, },
ContainerType::Section => html! { ContainerType::Section => html! {
section id=[self.id()] class=[self.classes("section")] { section id=[self.id()] class=[self.classes()] {
div class="container" { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(assets))
} }
} }
}, },
_ => html! { _ => html! {
div id=[self.id()] class=[self.classes("container")] { div id=[self.id()] class=[self.classes()] {
(self.components().render(assets)) (self.components().render(assets))
} }
} }
@ -74,25 +76,25 @@ impl PageComponent for Container {
impl Container { impl Container {
pub fn header() -> Self { pub fn header() -> Self {
let mut c = Container::new(); let mut c = Container::new().with_classes("header", ClassesOp::SetDefault);
c.container = ContainerType::Header; c.container = ContainerType::Header;
c c
} }
pub fn footer() -> Self { pub fn footer() -> Self {
let mut c = Container::new(); let mut c = Container::new().with_classes("footer", ClassesOp::SetDefault);
c.container = ContainerType::Footer; c.container = ContainerType::Footer;
c c
} }
pub fn main() -> Self { pub fn main() -> Self {
let mut c = Container::new(); let mut c = Container::new().with_classes("main", ClassesOp::SetDefault);
c.container = ContainerType::Main; c.container = ContainerType::Main;
c c
} }
pub fn section() -> Self { pub fn section() -> Self {
let mut c = Container::new(); let mut c = Container::new().with_classes("section", ClassesOp::SetDefault);
c.container = ContainerType::Section; c.container = ContainerType::Section;
c c
} }
@ -111,31 +113,63 @@ impl Container {
// Container BUILDER. // Container BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self self
} }
pub fn add_classes(mut self, classes: &str) -> Self { pub fn with_inner_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.add_classes(classes); self.alter_inner_classes(classes, op);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Container ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_inner_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.inner_classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -150,15 +184,15 @@ impl Container {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
}
pub fn inner_classes(&self) -> &Option<String> {
self.inner_classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -17,16 +17,17 @@ pub struct Button {
impl PageComponent for Button { impl PageComponent for Button {
fn new() -> Self { fn new() -> Self {
Button { Button {
renderable : always, renderable : render_always,
weight : 0, weight : 0,
button_type: ButtonType::Button, button_type: ButtonType::Button,
name : OptAttr::none(), name : OptAttr::new(),
value : OptAttr::none(), value : OptAttr::new(),
autofocus : OptAttr::none(), autofocus : OptAttr::new(),
disabled : OptAttr::none(), disabled : OptAttr::new(),
classes : Classes::none(), classes : Classes::new_with_default("btn btn-primary"),
template : "default".to_owned(), template : "default".to_owned(),
} }
.with_classes("form-button", ClassesOp::AddFirst)
} }
fn is_renderable(&self) -> bool { fn is_renderable(&self) -> bool {
@ -38,10 +39,10 @@ impl PageComponent for Button {
} }
fn default_render(&self, _: &mut PageAssets) -> Markup { fn default_render(&self, _: &mut PageAssets) -> Markup {
let (button_type, button_class) = match self.button_type() { let button_type = match self.button_type() {
ButtonType::Button => ("button", "btn btn-primary form-button"), ButtonType::Button => "button",
ButtonType::Reset => ("reset", "btn btn-primary form-reset" ), ButtonType::Reset => "reset",
ButtonType::Submit => ("submit", "btn btn-primary form-submit"), ButtonType::Submit => "submit",
}; };
let id = match self.name() { let id = match self.name() {
Some(name) => Some(concat_string!("edit-", name)), Some(name) => Some(concat_string!("edit-", name)),
@ -51,7 +52,7 @@ impl PageComponent for Button {
button button
type=(button_type) type=(button_type)
id=[id] id=[id]
class=[self.classes(button_class)] class=[self.classes()]
name=[self.name()] name=[self.name()]
value=[self.value()] value=[self.value()]
autofocus=[self.autofocus()] autofocus=[self.autofocus()]
@ -72,13 +73,17 @@ impl Button {
} }
pub fn reset(value: &str) -> Self { pub fn reset(value: &str) -> Self {
let mut button = Button::new().with_value(value); let mut button = Button::new()
.with_classes("form-reset", ClassesOp::Replace("form-button"))
.with_value(value);
button.button_type = ButtonType::Reset; button.button_type = ButtonType::Reset;
button button
} }
pub fn submit(value: &str) -> Self { pub fn submit(value: &str) -> Self {
let mut button = Button::new().with_value(value); let mut button = Button::new()
.with_classes("form-submit", ClassesOp::Replace("form-button"))
.with_value(value);
button.button_type = ButtonType::Submit; button.button_type = ButtonType::Submit;
button button
} }
@ -86,26 +91,68 @@ impl Button {
// Button BUILDER. // Button BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_name(mut self, name: &str) -> Self { pub fn with_name(mut self, name: &str) -> Self {
self.name.with_value(name); self.alter_name(name);
self self
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value.with_value(value); self.alter_value(value);
self self
} }
pub fn with_autofocus(mut self, toggle: bool) -> Self { pub fn with_autofocus(mut self, toggle: bool) -> Self {
self.alter_autofocus(toggle);
self
}
pub fn with_disabled(mut self, toggle: bool) -> Self {
self.alter_disabled(toggle);
self
}
pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.alter_classes(classes, op);
self
}
pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Button ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.with_value(name);
self
}
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.with_value(value);
self
}
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.with_value(match toggle { self.autofocus.with_value(match toggle {
true => "autofocus", true => "autofocus",
false => "", false => "",
@ -113,7 +160,7 @@ impl Button {
self self
} }
pub fn with_disabled(mut self, toggle: bool) -> Self { pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.with_value(match toggle { self.disabled.with_value(match toggle {
true => "disabled", true => "disabled",
false => "", false => "",
@ -121,17 +168,12 @@ impl Button {
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.set_classes(classes); self.classes.alter(classes, op);
self self
} }
pub fn add_classes(mut self, classes: &str) -> Self { pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.classes.add_classes(classes);
self
}
pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -158,15 +200,11 @@ impl Button {
self.disabled.option() self.disabled.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -20,21 +20,22 @@ pub struct Date {
impl PageComponent for Date { impl PageComponent for Date {
fn new() -> Self { fn new() -> Self {
Date { Date {
renderable : always, renderable : render_always,
weight : 0, weight : 0,
name : OptAttr::none(), name : OptAttr::new(),
value : OptAttr::none(), value : OptAttr::new(),
label : OptAttr::none(), label : OptAttr::new(),
placeholder : OptAttr::none(), placeholder : OptAttr::new(),
autofocus : OptAttr::none(), autofocus : OptAttr::new(),
autocomplete: OptAttr::none(), autocomplete: OptAttr::new(),
disabled : OptAttr::none(), disabled : OptAttr::new(),
readonly : OptAttr::none(), readonly : OptAttr::new(),
required : OptAttr::none(), required : OptAttr::new(),
help_text : OptAttr::none(), help_text : OptAttr::new(),
classes : Classes::none(), classes : Classes::new_with_default("form-item"),
template : "default".to_owned(), template : "default".to_owned(),
} }
.with_classes("form-type-date", ClassesOp::AddFirst)
} }
fn is_renderable(&self) -> bool { fn is_renderable(&self) -> bool {
@ -46,18 +47,12 @@ impl PageComponent for Date {
} }
fn default_render(&self, _: &mut PageAssets) -> Markup { fn default_render(&self, _: &mut PageAssets) -> Markup {
let (classes, id) = match self.name() { let id = match self.name() {
Some(name) => ( Some(name) => Some(concat_string!("edit-", name)),
concat_string!("form-item form-item-", name, " form-type-date"), None => None,
Some(concat_string!("edit-", name))
),
None => (
"form-item form-type-date".to_owned(),
None
)
}; };
html! { html! {
div class=[self.classes(classes.as_str())] { div class=[self.classes()] {
@match self.label() { @match self.label() {
Some(label) => label class="form-label" for=[&id] { Some(label) => label class="form-label" for=[&id] {
(label) " " (label) " "
@ -96,36 +91,108 @@ impl Date {
// Date BUILDER. // Date BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_name(mut self, name: &str) -> Self { pub fn with_name(mut self, name: &str) -> Self {
self.name.with_value(name); self.alter_name(name);
self self
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value.with_value(value); self.alter_value(value);
self self
} }
pub fn with_label(mut self, label: &str) -> Self { pub fn with_label(mut self, label: &str) -> Self {
self.label.with_value(label); self.alter_label(label);
self self
} }
pub fn with_placeholder(mut self, placeholder: &str) -> Self { pub fn with_placeholder(mut self, placeholder: &str) -> Self {
self.placeholder.with_value(placeholder); self.alter_placeholder(placeholder);
self self
} }
pub fn with_autofocus(mut self, toggle: bool) -> Self { pub fn with_autofocus(mut self, toggle: bool) -> Self {
self.alter_autofocus(toggle);
self
}
pub fn with_autocomplete(mut self, toggle: bool) -> Self {
self.alter_autocomplete(toggle);
self
}
pub fn with_disabled(mut self, toggle: bool) -> Self {
self.alter_disabled(toggle);
self
}
pub fn with_readonly(mut self, toggle: bool) -> Self {
self.alter_readonly(toggle);
self
}
pub fn with_required(mut self, toggle: bool) -> Self {
self.alter_required(toggle);
self
}
pub fn with_help_text(mut self, help_text: &str) -> Self {
self.alter_help_text(help_text);
self
}
pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.alter_classes(classes, op);
self
}
pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Date ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.with_value(name);
self
}
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.with_value(value);
self
}
pub fn alter_label(&mut self, label: &str) -> &mut Self {
self.label.with_value(label);
self
}
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
self.placeholder.with_value(placeholder);
self
}
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.with_value(match toggle { self.autofocus.with_value(match toggle {
true => "autofocus", true => "autofocus",
false => "", false => "",
@ -133,7 +200,7 @@ impl Date {
self self
} }
pub fn with_autocomplete(mut self, toggle: bool) -> Self { pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
self.autocomplete.with_value(match toggle { self.autocomplete.with_value(match toggle {
true => "", true => "",
false => "off", false => "off",
@ -141,7 +208,7 @@ impl Date {
self self
} }
pub fn with_disabled(mut self, toggle: bool) -> Self { pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.with_value(match toggle { self.disabled.with_value(match toggle {
true => "disabled", true => "disabled",
false => "", false => "",
@ -149,7 +216,7 @@ impl Date {
self self
} }
pub fn with_readonly(mut self, toggle: bool) -> Self { pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
self.readonly.with_value(match toggle { self.readonly.with_value(match toggle {
true => "readonly", true => "readonly",
false => "", false => "",
@ -157,7 +224,7 @@ impl Date {
self self
} }
pub fn with_required(mut self, toggle: bool) -> Self { pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
self.required.with_value(match toggle { self.required.with_value(match toggle {
true => "required", true => "required",
false => "", false => "",
@ -165,22 +232,17 @@ impl Date {
self self
} }
pub fn with_help_text(mut self, help_text: &str) -> Self { pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
self.help_text.with_value(help_text); self.help_text.with_value(help_text);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.set_classes(classes); self.classes.alter(classes, op);
self self
} }
pub fn add_classes(mut self, classes: &str) -> Self { pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.classes.add_classes(classes);
self
}
pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -227,15 +289,11 @@ impl Date {
self.help_text.option() self.help_text.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -17,14 +17,14 @@ pub struct Form {
impl PageComponent for Form { impl PageComponent for Form {
fn new() -> Self { fn new() -> Self {
Form { Form {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
elements : PageContainer::new(), elements : PageContainer::new(),
action : OptAttr::none(), action : OptAttr::new(),
charset : OptAttr::some("UTF-8"), charset : OptAttr::new_with_value("UTF-8"),
method : FormMethod::Post, method : FormMethod::Post,
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("form"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -45,7 +45,7 @@ impl PageComponent for Form {
html! { html! {
form form
id=[self.id()] id=[self.id()]
class=[self.classes("form")] class=[self.classes()]
action=[self.action()] action=[self.action()]
method=[method] method=[method]
accept-charset=[self.charset()] accept-charset=[self.charset()]
@ -72,46 +72,83 @@ impl Form {
// Form BUILDER. // Form BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_action(mut self, action: &str) -> Self { pub fn with_action(mut self, action: &str) -> Self {
self.action.with_value(action); self.alter_action(action);
self self
} }
pub fn with_charset(mut self, charset: &str) -> Self { pub fn with_charset(mut self, charset: &str) -> Self {
self.charset.with_value(charset); self.alter_charset(charset);
self self
} }
pub fn with_method(mut self, method: FormMethod) -> Self { pub fn with_method(mut self, method: FormMethod) -> Self {
self.method = method; self.alter_method(method);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self
}
pub fn add_classes(mut self, classes: &str) -> Self {
self.classes.add_classes(classes);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Form ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_action(&mut self, action: &str) -> &mut Self {
self.action.with_value(action);
self
}
pub fn alter_charset(&mut self, charset: &str) -> &mut Self {
self.charset.with_value(charset);
self
}
pub fn alter_method(&mut self, method: FormMethod) -> &mut Self {
self.method = method;
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -134,15 +171,11 @@ impl Form {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -10,8 +10,8 @@ impl PageComponent for Hidden {
fn new() -> Self { fn new() -> Self {
Hidden { Hidden {
weight: 0, weight: 0,
name : OptIden::none(), name : OptIden::new(),
value : OptAttr::none(), value : OptAttr::new(),
} }
} }
@ -32,24 +32,39 @@ impl PageComponent for Hidden {
impl Hidden { impl Hidden {
pub fn set(name: &str, value: &str) -> Self { pub fn set(name: &str, value: &str) -> Self {
Hidden::new() Hidden::new().with_name(name).with_value(value)
.with_name(name)
.with_value(value)
} }
// Hidden BUILDER. // Hidden BUILDER.
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_name(mut self, name: &str) -> Self { pub fn with_name(mut self, name: &str) -> Self {
self.name.with_value(name); self.alter_name(name);
self self
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.alter_value(value);
self
}
// Hidden ALTER.
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.with_value(name);
self
}
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.with_value(value); self.value.with_value(value);
self self
} }

View file

@ -26,25 +26,26 @@ pub struct Input {
impl PageComponent for Input { impl PageComponent for Input {
fn new() -> Self { fn new() -> Self {
Input { Input {
renderable : always, renderable : render_always,
weight : 0, weight : 0,
input_type : InputType::Textfield, input_type : InputType::Textfield,
name : OptIden::none(), name : OptIden::new(),
value : OptAttr::none(), value : OptAttr::new(),
label : OptAttr::none(), label : OptAttr::new(),
size : Some(60), size : Some(60),
minlength : None, minlength : None,
maxlength : Some(128), maxlength : Some(128),
placeholder : OptAttr::none(), placeholder : OptAttr::new(),
autofocus : OptAttr::none(), autofocus : OptAttr::new(),
autocomplete: OptAttr::none(), autocomplete: OptAttr::new(),
disabled : OptAttr::none(), disabled : OptAttr::new(),
readonly : OptAttr::none(), readonly : OptAttr::new(),
required : OptAttr::none(), required : OptAttr::new(),
help_text : OptAttr::none(), help_text : OptAttr::new(),
classes : Classes::none(), classes : Classes::new_with_default("form-item"),
template : "default".to_owned(), template : "default".to_owned(),
} }
.with_classes("form-type-textfield", ClassesOp::AddFirst)
} }
fn is_renderable(&self) -> bool { fn is_renderable(&self) -> bool {
@ -55,27 +56,28 @@ impl PageComponent for Input {
self.weight self.weight
} }
fn before_render(&mut self, _: &mut PageAssets) {
if let Some(name) = self.name() {
let class = concat_string!("form-item-", name);
self.alter_classes(class.as_str(), ClassesOp::AddFirst);
}
}
fn default_render(&self, _: &mut PageAssets) -> Markup { fn default_render(&self, _: &mut PageAssets) -> Markup {
let (type_input, type_class) = match self.input_type() { let type_input = match self.input_type() {
InputType::Email => ("email", "form-type-email"), InputType::Email => "email",
InputType::Password => ("password", "form-type-password"), InputType::Password => "password",
InputType::Search => ("search", "form-type-search"), InputType::Search => "search",
InputType::Telephone => ("tel", "form-type-telephone"), InputType::Telephone => "tel",
InputType::Textfield => ("text", "form-type-textfield"), InputType::Textfield => "text",
InputType::Url => ("url", "form-type-url") InputType::Url => "url",
}; };
let (class, id) = match self.name() { let id = match self.name() {
Some(name) => ( Some(name) => Some(concat_string!("edit-", name)),
concat_string!("form-item form-item-", name, " ", type_class), None => None,
Some(concat_string!("edit-", name))
),
None => (
concat_string!("form-item ", type_class),
None
)
}; };
html! { html! {
div class=(class) { div class=[self.classes()] {
@match self.label() { @match self.label() {
Some(label) => label class="form-label" for=[&id] { Some(label) => label class="form-label" for=[&id] {
(label) " " (label) " "
@ -118,31 +120,36 @@ impl Input {
} }
pub fn password() -> Self { pub fn password() -> Self {
let mut input = Input::new(); let mut input = Input::new()
.with_classes("form-type-password", ClassesOp::Replace("form-type-textfield"));
input.input_type = InputType::Password; input.input_type = InputType::Password;
input input
} }
pub fn search() -> Self { pub fn search() -> Self {
let mut input = Input::new(); let mut input = Input::new()
.with_classes("form-type-search", ClassesOp::Replace("form-type-textfield"));
input.input_type = InputType::Search; input.input_type = InputType::Search;
input input
} }
pub fn email() -> Self { pub fn email() -> Self {
let mut input = Input::new(); let mut input = Input::new()
.with_classes("form-type-email", ClassesOp::Replace("form-type-textfield"));
input.input_type = InputType::Email; input.input_type = InputType::Email;
input input
} }
pub fn telephone() -> Self { pub fn telephone() -> Self {
let mut input = Input::new(); let mut input = Input::new()
.with_classes("form-type-telephone", ClassesOp::Replace("form-type-textfield"));
input.input_type = InputType::Telephone; input.input_type = InputType::Telephone;
input input
} }
pub fn url() -> Self { pub fn url() -> Self {
let mut input = Input::new(); let mut input = Input::new()
.with_classes("form-type-url", ClassesOp::Replace("form-type-textfield"));
input.input_type = InputType::Url; input.input_type = InputType::Url;
input input
} }
@ -150,51 +157,138 @@ impl Input {
// Input BUILDER. // Input BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_name(mut self, name: &str) -> Self { pub fn with_name(mut self, name: &str) -> Self {
self.name.with_value(name); self.alter_name(name);
self self
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value.with_value(value); self.alter_value(value);
self self
} }
pub fn with_label(mut self, label: &str) -> Self { pub fn with_label(mut self, label: &str) -> Self {
self.label.with_value(label); self.alter_label(label);
self self
} }
pub fn with_size(mut self, size: Option<u16>) -> Self { pub fn with_size(mut self, size: Option<u16>) -> Self {
self.size = size; self.alter_size(size);
self self
} }
pub fn with_minlength(mut self, minlength: Option<u16>) -> Self { pub fn with_minlength(mut self, minlength: Option<u16>) -> Self {
self.minlength = minlength; self.alter_minlength(minlength);
self self
} }
pub fn with_maxlength(mut self, maxlength: Option<u16>) -> Self { pub fn with_maxlength(mut self, maxlength: Option<u16>) -> Self {
self.maxlength = maxlength; self.alter_maxlength(maxlength);
self self
} }
pub fn with_placeholder(mut self, placeholder: &str) -> Self { pub fn with_placeholder(mut self, placeholder: &str) -> Self {
self.placeholder.with_value(placeholder); self.alter_placeholder(placeholder);
self self
} }
pub fn with_autofocus(mut self, toggle: bool) -> Self { pub fn with_autofocus(mut self, toggle: bool) -> Self {
self.alter_autofocus(toggle);
self
}
pub fn with_autocomplete(mut self, toggle: bool) -> Self {
self.alter_autocomplete(toggle);
self
}
pub fn with_disabled(mut self, toggle: bool) -> Self {
self.alter_disabled(toggle);
self
}
pub fn with_readonly(mut self, toggle: bool) -> Self {
self.alter_readonly(toggle);
self
}
pub fn with_required(mut self, toggle: bool) -> Self {
self.alter_required(toggle);
self
}
pub fn with_help_text(mut self, help_text: &str) -> Self {
self.alter_help_text(help_text);
self
}
pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.alter_classes(classes, op);
self
}
pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Input ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.with_value(name);
self
}
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.with_value(value);
self
}
pub fn alter_label(&mut self, label: &str) -> &mut Self {
self.label.with_value(label);
self
}
pub fn alter_size(&mut self, size: Option<u16>) -> &mut Self {
self.size = size;
self
}
pub fn alter_minlength(&mut self, minlength: Option<u16>) -> &mut Self {
self.minlength = minlength;
self
}
pub fn alter_maxlength(&mut self, maxlength: Option<u16>) -> &mut Self {
self.maxlength = maxlength;
self
}
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
self.placeholder.with_value(placeholder);
self
}
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.with_value(match toggle { self.autofocus.with_value(match toggle {
true => "autofocus", true => "autofocus",
false => "", false => "",
@ -202,7 +296,7 @@ impl Input {
self self
} }
pub fn with_autocomplete(mut self, toggle: bool) -> Self { pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
self.autocomplete.with_value(match toggle { self.autocomplete.with_value(match toggle {
true => "", true => "",
false => "off", false => "off",
@ -210,7 +304,7 @@ impl Input {
self self
} }
pub fn with_disabled(mut self, toggle: bool) -> Self { pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.with_value(match toggle { self.disabled.with_value(match toggle {
true => "disabled", true => "disabled",
false => "", false => "",
@ -218,7 +312,7 @@ impl Input {
self self
} }
pub fn with_readonly(mut self, toggle: bool) -> Self { pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
self.readonly.with_value(match toggle { self.readonly.with_value(match toggle {
true => "readonly", true => "readonly",
false => "", false => "",
@ -226,7 +320,7 @@ impl Input {
self self
} }
pub fn with_required(mut self, toggle: bool) -> Self { pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
self.required.with_value(match toggle { self.required.with_value(match toggle {
true => "required", true => "required",
false => "", false => "",
@ -234,22 +328,17 @@ impl Input {
self self
} }
pub fn with_help_text(mut self, help_text: &str) -> Self { pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
self.help_text.with_value(help_text); self.help_text.with_value(help_text);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.set_classes(classes); self.classes.alter(classes, op);
self self
} }
pub fn add_classes(mut self, classes: &str) -> Self { pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.classes.add_classes(classes);
self
}
pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -312,15 +401,11 @@ impl Input {
self.help_text.option() self.help_text.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -12,11 +12,11 @@ pub struct Column {
impl PageComponent for Column { impl PageComponent for Column {
fn new() -> Self { fn new() -> Self {
Column { Column {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
components: PageContainer::new(), components: PageContainer::new(),
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("col"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -35,7 +35,7 @@ impl PageComponent for Column {
fn default_render(&self, assets: &mut PageAssets) -> Markup { fn default_render(&self, assets: &mut PageAssets) -> Markup {
html! { html! {
div id=[self.id()] class=[self.classes("col")] { div id=[self.id()] class=[self.classes()] {
(self.components().render(assets)) (self.components().render(assets))
} }
} }
@ -58,31 +58,53 @@ impl Column {
// Column BUILDER. // Column BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self
}
pub fn add_classes(mut self, classes: &str) -> Self {
self.classes.add_classes(classes);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Column ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -93,15 +115,11 @@ impl Column {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -12,11 +12,11 @@ pub struct Row {
impl PageComponent for Row { impl PageComponent for Row {
fn new() -> Self { fn new() -> Self {
Row { Row {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
columns : PageContainer::new(), columns : PageContainer::new(),
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("row"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -35,7 +35,7 @@ impl PageComponent for Row {
fn default_render(&self, assets: &mut PageAssets) -> Markup { fn default_render(&self, assets: &mut PageAssets) -> Markup {
html! { html! {
div id=[self.id()] class=[self.classes("row")] { div id=[self.id()] class=[self.classes()] {
(self.columns().render(assets)) (self.columns().render(assets))
} }
} }
@ -58,36 +58,53 @@ impl Row {
// Row BUILDER. // Row BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self
}
pub fn set_classes_ref(&mut self, classes: &str) -> &Self {
self.classes.set_classes(classes);
self
}
pub fn add_classes(mut self, classes: &str) -> Self {
self.classes.add_classes(classes);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Row ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -98,15 +115,11 @@ impl Row {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -12,11 +12,11 @@ pub struct Image {
impl PageComponent for Image { impl PageComponent for Image {
fn new() -> Self { fn new() -> Self {
Image { Image {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
source : OptAttr::none(), source : OptAttr::new(),
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("img-fluid"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -34,7 +34,7 @@ impl PageComponent for Image {
img img
src=[self.source()] src=[self.source()]
id=[self.id()] id=[self.id()]
class=[self.classes("img-fluid")]; class=[self.classes()];
} }
} }
} }
@ -47,36 +47,63 @@ impl Image {
// Image BUILDER. // Image BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_source(mut self, source: &str) -> Self { pub fn with_source(mut self, source: &str) -> Self {
self.source.with_value(source); self.alter_source(source);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self
}
pub fn add_classes(mut self, classes: &str) -> Self {
self.classes.add_classes(classes);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Image ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_source(&mut self, source: &str) -> &mut Self {
self.source.with_value(source);
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -91,15 +118,11 @@ impl Image {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -23,7 +23,7 @@ pub struct MenuItem {
impl PageComponent for MenuItem { impl PageComponent for MenuItem {
fn new() -> Self { fn new() -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::Void, item_type : MenuItemType::Void,
} }
@ -72,7 +72,7 @@ impl PageComponent for MenuItem {
impl MenuItem { impl MenuItem {
pub fn label(label: &str) -> Self { pub fn label(label: &str) -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::Label(label.to_owned()), item_type : MenuItemType::Label(label.to_owned()),
} }
@ -80,7 +80,7 @@ impl MenuItem {
pub fn link(label: &str, path: &str) -> Self { pub fn link(label: &str, path: &str) -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::Link( item_type : MenuItemType::Link(
label.to_owned(), label.to_owned(),
@ -91,7 +91,7 @@ impl MenuItem {
pub fn link_blank(label: &str, path: &str) -> Self { pub fn link_blank(label: &str, path: &str) -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::LinkBlank( item_type : MenuItemType::LinkBlank(
label.to_owned(), label.to_owned(),
@ -102,7 +102,7 @@ impl MenuItem {
pub fn html(html: Markup) -> Self { pub fn html(html: Markup) -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::Html(html), item_type : MenuItemType::Html(html),
} }
@ -110,7 +110,7 @@ impl MenuItem {
pub fn separator() -> Self { pub fn separator() -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::Separator, item_type : MenuItemType::Separator,
} }
@ -118,7 +118,7 @@ impl MenuItem {
pub fn submenu(label: &str, menu: Menu) -> Self { pub fn submenu(label: &str, menu: Menu) -> Self {
MenuItem { MenuItem {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
item_type : MenuItemType::Submenu( item_type : MenuItemType::Submenu(
label.to_owned(), label.to_owned(),
@ -130,11 +130,23 @@ impl MenuItem {
// MenuItem BUILDER. // MenuItem BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.alter_weight(weight);
self
}
// MenuItem ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight; self.weight = weight;
self self
} }
@ -162,11 +174,11 @@ pub struct Menu {
impl PageComponent for Menu { impl PageComponent for Menu {
fn new() -> Self { fn new() -> Self {
Menu { Menu {
renderable: always, renderable: render_always,
weight : 0, weight : 0,
items : PageContainer::new(), items : PageContainer::new(),
id : OptIden::none(), id : OptIden::new(),
classes : Classes::none(), classes : Classes::new_with_default("sm sm-clean"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -194,7 +206,7 @@ impl PageComponent for Menu {
let id = assets.serial_id(self.name(), self.id()); let id = assets.serial_id(self.name(), self.id());
html! { html! {
ul id=(id) class=[self.classes("sm sm-clean")] { ul id=(id) class=[self.classes()] {
(self.items().render(assets)) (self.items().render(assets))
} }
script type="text/javascript" defer { script type="text/javascript" defer {
@ -223,31 +235,53 @@ impl Menu {
// Menu BUILDER. // Menu BUILDER.
pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self {
self.renderable = renderable; self.alter_renderable(renderable);
self self
} }
pub fn with_weight(mut self, weight: i8) -> Self { pub fn with_weight(mut self, weight: i8) -> Self {
self.weight = weight; self.alter_weight(weight);
self self
} }
pub fn with_id(mut self, id: &str) -> Self { pub fn with_id(mut self, id: &str) -> Self {
self.id.with_value(id); self.alter_id(id);
self self
} }
pub fn set_classes(mut self, classes: &str) -> Self { pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self {
self.classes.set_classes(classes); self.alter_classes(classes, op);
self
}
pub fn add_classes(mut self, classes: &str) -> Self {
self.classes.add_classes(classes);
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.alter_template(template);
self
}
// Menu ALTER.
pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self {
self.renderable = renderable;
self
}
pub fn alter_weight(&mut self, weight: i8) -> &mut Self {
self.weight = weight;
self
}
pub fn alter_id(&mut self, id: &str) -> &mut Self {
self.id.with_value(id);
self
}
pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.classes.alter(classes, op);
self
}
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned(); self.template = template.to_owned();
self self
} }
@ -258,15 +292,11 @@ impl Menu {
self.id.option() self.id.option()
} }
pub fn classes(&self, default: &str) -> Option<String> { pub fn classes(&self) -> &Option<String> {
self.classes.option(default) self.classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
self.template.as_str() self.template.as_str()
} }
} }
fn always() -> bool {
true
}

View file

@ -32,33 +32,21 @@ impl ThemeTrait for BulmixTheme {
.add_jquery(); .add_jquery();
} }
fn render_component( fn before_render_component(
&self, &self,
component: &mut dyn PageComponent, component: &mut dyn PageComponent,
assets: &mut PageAssets _assets: &mut PageAssets
) -> Option<Markup> { ) {
match component.name() { match component.name() {
"GridRow" => { "GridRow" => {
let row = component.downcast_mut::<grid::Row>().unwrap(); let row = component.downcast_mut::<grid::Row>().unwrap();
row.set_classes_ref("Prueba"); row.alter_classes("columns", ClassesOp::SetDefault);
None
/*
Some(html! {
div id=[row.id()] class=[row.classes("columns")] {
(row.columns().render(assets))
}
})
*/
}, },
"GridColumn" => { "GridColumn" => {
let col = component.downcast_ref::<grid::Column>().unwrap(); let col = component.downcast_mut::<grid::Column>().unwrap();
Some(html! { col.alter_classes("column", ClassesOp::SetDefault);
div id=[col.id()] class=[col.classes("column")] {
(col.components().render(assets))
}
})
}, },
_ => None _ => {},
} }
} }
} }

View file

@ -1,23 +1,82 @@
use crate::concat_string; use crate::concat_string;
pub struct Classes(String); pub enum ClassesOp {
Add,
AddAfter(&'static str),
AddBefore(&'static str),
AddFirst,
Replace(&'static str),
Reset,
SetDefault,
}
pub struct Classes {
default: String,
added : String,
option : Option<String>,
}
impl Classes { impl Classes {
pub fn none() -> Self { pub fn new() -> Self {
Classes("".to_owned()) Classes {
default: "".to_owned(),
added : "".to_owned(),
option : None,
}
} }
pub fn set_classes(&mut self, classes: &str) -> &mut Self { pub fn new_with_default(default: &str) -> Self {
self.0 = classes.to_owned(); let mut classes = Self::new();
classes.alter(default, ClassesOp::SetDefault);
classes
}
pub fn alter(&mut self, classes: &str, op: ClassesOp) -> &Self {
let classes = classes.trim();
match op {
ClassesOp::Add => self.added.push_str(concat_string!(" ", classes).as_str()),
ClassesOp::AddAfter(class) => {
let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect();
match v_added.iter().position(|c| c.eq(&class)) {
Some(pos) => v_added.insert(pos + 1, classes),
_ => v_added.push(classes),
}
self.added = v_added.join(" ");
},
ClassesOp::AddBefore(class) => {
let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect();
match v_added.iter().position(|c| c.eq(&class)) {
Some(pos) => v_added.insert(pos, classes),
_ => v_added.insert(0, classes),
}
self.added = v_added.join(" ");
},
ClassesOp::AddFirst => self.added = concat_string!(classes, " ", self.added),
ClassesOp::Replace(class) => {
let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect();
match v_added.iter().position(|c| c.eq(&class)) {
Some(pos) => {
v_added.remove(pos);
v_added.insert(pos, classes);
},
_ => v_added.push(classes),
}
self.added = v_added.join(" ");
},
ClassesOp::Reset => self.added = classes.to_owned(),
ClassesOp::SetDefault => self.default = classes.to_owned(),
}
self.option = Some(concat_string!(self.default, " ", self.added).trim().to_owned());
self self
} }
pub fn add_classes(&mut self, classes: &str) -> &mut Self { pub fn option(&self) -> &Option<String> {
self.0 = concat_string!(self.0, " ", classes).trim().to_owned(); &self.option
self
}
pub fn option(&self, default: &str) -> Option<String> {
Some(concat_string!(default.to_owned(), " ", self.0).trim().to_owned())
} }
} }

View file

@ -5,4 +5,4 @@ pub use optiden::OptIden;
mod optattr; mod optattr;
pub use optattr::OptAttr; pub use optattr::OptAttr;
mod classes; mod classes;
pub use classes::Classes; pub use classes::{Classes, ClassesOp};

View file

@ -1,14 +1,14 @@
pub struct OptAttr(Option<String>); pub struct OptAttr(Option<String>);
impl OptAttr { impl OptAttr {
pub fn none() -> Self { pub fn new() -> Self {
OptAttr(None) OptAttr(None)
} }
pub fn some(value: &str) -> Self { pub fn new_with_value(value: &str) -> Self {
let mut o = OptAttr(None); let mut option = Self::new();
o.with_value(value); option.with_value(value);
o option
} }
pub fn with_value(&mut self, value: &str) -> &mut Self { pub fn with_value(&mut self, value: &str) -> &mut Self {

View file

@ -1,17 +1,17 @@
pub struct OptIden(Option<String>); pub struct OptIden(Option<String>);
impl OptIden { impl OptIden {
pub fn none() -> Self { pub fn new() -> Self {
OptIden(None) OptIden(None)
} }
pub fn some(id: &str) -> Self { pub fn new_with_value(id: &str) -> Self {
let mut o = OptIden(None); let mut option = Self::new();
o.with_value(id); option.with_value(id);
o option
} }
pub fn with_value(&mut self, id: &str) -> &mut Self { pub fn with_value(&mut self, id: &str) -> &Self {
let id = id.trim(); let id = id.trim();
self.0 = match id.is_empty() { self.0 = match id.is_empty() {
true => None, true => None,

View file

@ -257,7 +257,7 @@ impl PageAssets {
/// Assets GETTERS. /// Assets GETTERS.
pub fn theme(&mut self) -> &'static dyn ThemeTrait { pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait {
self.theme self.theme
} }

View file

@ -33,6 +33,10 @@ pub trait PageComponent: Downcast + Send + Sync {
0 0
} }
#[allow(unused_variables)]
fn before_render(&mut self, assets: &mut PageAssets) {
}
#[allow(unused_variables)] #[allow(unused_variables)]
fn default_render(&self, assets: &mut PageAssets) -> Markup { fn default_render(&self, assets: &mut PageAssets) -> Markup {
html! {} html! {}

View file

@ -17,3 +17,6 @@ pub use page::Page;
pub use page::render_component; pub use page::render_component;
pub use page::add_component_to; pub use page::add_component_to;
pub fn render_always() -> bool { true }
pub fn render_never() -> bool { false }

View file

@ -1,6 +1,6 @@
use crate::{Lazy, app, trace}; use crate::{Lazy, app, trace};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::{Classes, DOCTYPE, Markup, OptAttr, html}; use crate::html::*;
use crate::response::page::*; use crate::response::page::*;
use std::sync::RwLock; use std::sync::RwLock;
@ -55,18 +55,18 @@ impl<'a> Page<'a> {
pub fn new() -> Self { pub fn new() -> Self {
Page { Page {
language : match &*DEFAULT_LANGUAGE { language : match &*DEFAULT_LANGUAGE {
Some(language) => OptAttr::some(language), Some(language) => OptAttr::new_with_value(language),
_ => OptAttr::none(), _ => OptAttr::new(),
}, },
direction : match &*DEFAULT_DIRECTION { direction : match &*DEFAULT_DIRECTION {
Some(direction) => OptAttr::some(direction), Some(direction) => OptAttr::new_with_value(direction),
_ => OptAttr::none(), _ => OptAttr::new(),
}, },
title : OptAttr::none(), title : OptAttr::new(),
description : OptAttr::none(), description : OptAttr::new(),
assets : PageAssets::new(), assets : PageAssets::new(),
regions : COMPONENTS.read().unwrap().clone(), regions : COMPONENTS.read().unwrap().clone(),
body_classes: Classes::none(), body_classes: Classes::new_with_default("body"),
template : "default".to_owned(), template : "default".to_owned(),
} }
} }
@ -110,13 +110,8 @@ impl<'a> Page<'a> {
self self
} }
pub fn set_body_classes(&mut self, classes: &str) -> &mut Self { pub fn alter_body_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self {
self.body_classes.set_classes(classes); self.body_classes.alter(classes, op);
self
}
pub fn add_body_classes(&mut self, classes: &str) -> &mut Self {
self.body_classes.add_classes(classes);
self self
} }
@ -147,8 +142,8 @@ impl<'a> Page<'a> {
&mut self.assets &mut self.assets
} }
pub fn body_classes(&self, default: &str) -> Option<String> { pub fn body_classes(&self) -> &Option<String> {
self.body_classes.option(default) self.body_classes.option()
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
@ -192,14 +187,15 @@ impl<'a> Page<'a> {
} }
} }
pub fn render_component( pub fn render_component(component: &mut dyn PageComponent, assets: &mut PageAssets) -> Markup {
component: &mut dyn PageComponent, component.before_render(assets);
assets: &mut PageAssets assets.theme().before_render_component(component, assets);
) -> Markup {
match component.is_renderable() { match component.is_renderable() {
true => match assets.theme().render_component(component, assets) { true => {
Some(html) => html, match assets.theme().render_component(component, assets) {
None => component.default_render(assets) Some(html) => html,
None => component.default_render(assets)
}
}, },
false => html! {} false => html! {}
} }

View file

@ -55,7 +55,7 @@ pub trait ThemeTrait: Send + Sync {
fn render_page_body(&self, page: &mut Page) -> Markup { fn render_page_body(&self, page: &mut Page) -> Markup {
html! { html! {
body class=[page.body_classes("body")] { body class=[page.body_classes()] {
@match page.template() { @match page.template() {
"admin" => { "admin" => {
@for region in &["top-menu", "side-menu", "content"] { @for region in &["top-menu", "side-menu", "content"] {
@ -75,10 +75,29 @@ pub trait ThemeTrait: Send + Sync {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn render_component( fn before_render_component(
&self, &self,
component: &mut dyn PageComponent, component: &mut dyn PageComponent,
assets: &mut PageAssets assets: &mut PageAssets
) {
/*
Cómo usarlo:
match component.name() {
"Block" => {
let block = component.downcast_mut::<Block>().unwrap();
block.alter_title("New title");
},
_ => {},
}
*/
}
#[allow(unused_variables)]
fn render_component(
&self,
component: &dyn PageComponent,
assets: &mut PageAssets
) -> Option<Markup> { ) -> Option<Markup> {
None None
/* /*
@ -89,10 +108,10 @@ pub trait ThemeTrait: Send + Sync {
let block = component.downcast_ref::<Block>().unwrap(); let block = component.downcast_ref::<Block>().unwrap();
match block.template() { match block.template() {
"default" => Some(block_default(block)), "default" => Some(block_default(block)),
_ => None _ => None,
} }
}, },
_ => None _ => None,
} }
*/ */
} }