use std::borrow::BorrowMut;
use std::ops::DerefMut;
use crate::DefaultModifiers;
use crate::Renderable;
use crate::components::badge::{Badge, BadgeSupport};
use crate::components::icons::IconPack;
use crate::components::{BadgeModifiers, Icon, Text, TextStyle};
use crate::node::Node;
#[derive(Debug, Clone)]
pub enum ButtonStyle {
SmallLink,
Link,
Flat,
Outlined,
Filled,
}
#[derive(Debug, Clone)]
pub struct Button {
node: Node,
badge: Option<Badge>,
pub label: Option<String>,
pub style: ButtonStyle,
pub icon: Option<Box<dyn IconPack>>,
}
impl Button {
pub fn new(label: &str, style: ButtonStyle) -> Self {
let mut button = Button {
node: Node::default(),
badge: None,
label: Some(label.to_string()),
style,
icon: None,
};
button.tag("button").set_attr("type", "button");
button
}
pub fn icon_only<T>(icon: T, style: ButtonStyle) -> Self
where
T: 'static + IconPack,
{
let mut button = Button {
node: Node::default(),
badge: None,
label: None,
style,
icon: Some(Box::new(icon)),
};
button.tag("button").set_attr("type", "button");
button
}
pub fn destructive(&mut self) -> &mut Self {
self.add_class(
format!("button--{:?}--destructive", self.style)
.to_lowercase()
.as_str(),
)
}
pub fn disabled(&mut self, is_disabled: bool) -> &mut Self {
if is_disabled {
self.add_class(
format!("button--{:?}--disabled", self.style)
.to_lowercase()
.as_str(),
)
.set_attr("disabled", "disabled")
} else {
self
}
}
pub fn reversed(&mut self, is_reversed: bool) -> &mut Self {
if is_reversed {
self.add_class("button--reversed")
} else {
self
}
}
pub fn attach_to_form(&mut self, form_name: &str) -> &mut Self {
self.set_attr("form", form_name).set_attr("type", "submit")
}
pub fn attach_to_file_input(&mut self, input_id: &str) -> &mut Self {
self.set_attr("data-input-file", &format!("file-input-{}", input_id))
}
pub fn close_popup(&mut self) -> &mut Self {
self.add_class("popup__window-controls")
}
pub fn action(&mut self, url: &str) -> &mut Self {
self.set_attr("href", url).tag("a")
}
pub fn icon<T>(&mut self, icon: T) -> &mut Self
where
T: 'static + IconPack,
{
self.icon = Some(Box::new(icon));
self
}
}
impl std::ops::Deref for Button {
type Target = Node;
fn deref(&self) -> &Self::Target {
&self.node
}
}
impl std::ops::DerefMut for Button {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.node
}
}
impl DefaultModifiers for Button {}
impl BadgeSupport for Button {
fn add_badge(&mut self, badge: Badge) {
self.badge = Some(badge);
}
}
impl BadgeModifiers for Button {}
impl Renderable for Button {
fn render(mut self) -> Node {
let button_style = format!("button--{:?}", self.style).to_lowercase();
self.add_class("button")
.add_class(&button_style)
.set_attr("role", "button");
if self.label.is_none() && self.icon.is_some() {
self.add_class("button--icon-only");
}
if let Some(icon) = self.icon {
let mut icon = Icon::new(icon).size(match self.style {
ButtonStyle::SmallLink => 14,
_ => 16,
});
if self.label.is_none() {
icon.size(match self.style {
ButtonStyle::SmallLink => 16,
_ => 24,
});
icon.stroke_width(2);
}
self.node.children.push(icon.render());
}
if let Some(label) = self.label {
let text = Text::new(
label.as_str(),
match self.style {
ButtonStyle::SmallLink => TextStyle::Caption,
_ => TextStyle::Button,
},
)
.render();
self.node.children.push(text);
}
if let Some(badge) = self.badge {
self.node.children.push(badge.render());
}
self.node
}
}