add border

This commit is contained in:
JMARyA 2025-01-20 06:44:06 +01:00
parent 5d4aa21edd
commit 35669c423c
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
4 changed files with 273 additions and 4 deletions

View file

@ -23,6 +23,7 @@ pub mod prelude {
pub use super::primitives::animation::{Animated, Animation, Delay, Duration, Scope, Timing};
pub use super::primitives::aspect::Aspect;
pub use super::primitives::background::Background;
pub use super::primitives::border::{Border, BorderSide, BorderSize, BorderStyle};
pub use super::primitives::container::Container;
pub use super::primitives::cursor::Cursor;
pub use super::primitives::div::Div;

166
src/ui/primitives/border.rs Normal file
View file

@ -0,0 +1,166 @@
use maud::{Markup, Render, html};
use crate::ui::{UIWidget, color::UIColor};
pub enum BorderSize {
_0,
_2,
_4,
_8,
}
impl BorderSize {
pub const fn to_value(&self) -> &str {
match self {
BorderSize::_0 => "0",
BorderSize::_2 => "2",
BorderSize::_4 => "4",
BorderSize::_8 => "8",
}
}
}
pub enum BorderSide {
X,
Y,
Start,
End,
Top,
Right,
Bottom,
Left,
}
impl BorderSide {
pub const fn to_value(&self) -> &str {
match self {
BorderSide::X => "x",
BorderSide::Y => "y",
BorderSide::Start => "s",
BorderSide::End => "e",
BorderSide::Top => "t",
BorderSide::Right => "r",
BorderSide::Bottom => "b",
BorderSide::Left => "l",
}
}
}
pub enum BorderStyle {
Solid,
Dashed,
Dotted,
Double,
Hidden,
None,
}
impl BorderStyle {
pub const fn to_value(&self) -> &str {
match self {
BorderStyle::Solid => "border-solid",
BorderStyle::Dashed => "border-dashed",
BorderStyle::Dotted => "border-dotted",
BorderStyle::Double => "border-double",
BorderStyle::Hidden => "border-hidden",
BorderStyle::None => "border-none",
}
}
}
#[allow(non_snake_case)]
pub fn Border<T: UIWidget + 'static>(inner: T) -> BorderWidget {
BorderWidget(Box::new(inner), None, None, None, None)
}
pub struct BorderWidget(
Box<dyn UIWidget>,
Option<BorderSize>,
Option<BorderSide>,
Option<Box<dyn UIColor>>,
Option<BorderStyle>,
);
impl BorderWidget {
#[must_use]
pub fn size(mut self, size: BorderSize) -> Self {
self.1 = Some(size);
self
}
#[must_use]
pub const fn side(mut self, side: BorderSide) -> Self {
self.2 = Some(side);
self
}
#[must_use]
pub const fn style(mut self, style: BorderStyle) -> Self {
self.4 = Some(style);
self
}
#[must_use]
pub fn color<C: UIColor + 'static>(mut self, color: C) -> Self {
self.3 = Some(Box::new(color));
self
}
fn border_class(&self) -> String {
if let Some(side) = &self.2 {
if let Some(size) = &self.1 {
return format!("border-{}-{}", side.to_value(), size.to_value());
}
} else if let Some(size) = &self.1 {
return format!("border-{}", size.to_value());
}
"border".to_owned()
}
}
impl Render for BorderWidget {
fn render(&self) -> Markup {
self.render_with_class("")
}
}
impl UIWidget for BorderWidget {
fn can_inherit(&self) -> bool {
true
}
fn base_class(&self) -> Vec<String> {
let mut ret = vec![self.border_class()];
if let Some(color) = &self.3 {
ret.push(format!("border-{}", color.color_class()));
}
if let Some(style) = &self.4 {
ret.push(style.to_value().to_string());
}
ret
}
fn extended_class(&self) -> Vec<String> {
let mut c = self.base_class();
c.extend_from_slice(&self.0.extended_class());
c
}
fn render_with_class(&self, class: &str) -> Markup {
if self.0.as_ref().can_inherit() {
self.0
.as_ref()
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
} else {
html! {
div class=(format!("{} {class}", self.base_class().join(" "))) {
(self.0.as_ref())
}
}
}
}
}

View file

@ -1,11 +1,11 @@
use crate::ui::UIWidget;
use crate::ui::{UIWidget, color::UIColor};
use maud::{Markup, Render, html};
use super::space::{Fraction, ScreenValue};
#[allow(non_snake_case)]
pub fn Flex<T: UIWidget + 'static>(inner: T) -> FlexWidget {
FlexWidget(Box::new(inner), vec![], false)
FlexWidget(Box::new(inner), vec![], false, None)
}
pub enum Justify {
@ -19,7 +19,7 @@ pub enum Justify {
Stretch,
}
pub struct FlexWidget(Box<dyn UIWidget>, Vec<String>, bool);
pub struct FlexWidget(Box<dyn UIWidget>, Vec<String>, bool, Option<Direction>);
impl Render for FlexWidget {
fn render(&self) -> Markup {
@ -41,9 +41,65 @@ impl FlexWidget {
self
}
#[must_use]
pub fn divide_style(mut self, style: DivideStyle) -> Self {
self.1.push(style.to_value().to_string());
self
}
#[must_use]
pub fn divide_color<C: UIColor + 'static>(mut self, color: C) -> Self {
self.1.push(format!("divide-{}", color.color_class()));
self
}
#[must_use]
pub fn divide_x(mut self, width: DivideWidth) -> Self {
let reversed = self
.3
.as_ref()
.map(|x| match x {
Direction::Row => false,
Direction::RowReverse => true,
Direction::Column => false,
Direction::ColumnReverse => true,
})
.unwrap_or_default();
self.1.push(format!("divide-x-{}", width.to_value()));
if reversed {
self.1.push("divide-x-reverse".to_string());
}
self
}
#[must_use]
pub fn divide_y(mut self, width: DivideWidth) -> Self {
let reversed = self
.3
.as_ref()
.map(|x| match x {
Direction::Row => false,
Direction::RowReverse => true,
Direction::Column => false,
Direction::ColumnReverse => true,
})
.unwrap_or_default();
self.1.push(format!("divide-y-{}", width.to_value()));
if reversed {
self.1.push("divide-y-reverse".to_string());
}
self
}
#[must_use]
pub fn direction(mut self, direction: Direction) -> Self {
self.1.push(format!("flex-{}", direction.to_value()));
self.3 = Some(direction);
self
}
@ -95,6 +151,26 @@ impl FlexWidget {
}
}
pub enum DivideWidth {
Custom(u64),
_0,
_2,
_4,
_8,
}
impl DivideWidth {
pub fn to_value(&self) -> String {
match self {
DivideWidth::Custom(s) => format!("[{s}px]"),
DivideWidth::_0 => "0".to_string(),
DivideWidth::_2 => "2".to_string(),
DivideWidth::_4 => "4".to_string(),
DivideWidth::_8 => "8".to_string(),
}
}
}
pub enum Direction {
Row,
RowReverse,
@ -136,6 +212,11 @@ impl UIWidget for FlexWidget {
fn base_class(&self) -> Vec<String> {
let mut res = vec!["flex".to_string()];
if let Some(direction) = &self.3 {
res.push(format!("flex-{}", direction.to_value()));
}
res.extend_from_slice(&self.1);
res
}
@ -399,3 +480,23 @@ impl UIWidget for OrderWidget {
}
}
}
pub enum DivideStyle {
Solid,
Dashed,
Dotted,
Double,
None,
}
impl DivideStyle {
pub const fn to_value(&self) -> &str {
match self {
DivideStyle::Solid => "divide-solid",
DivideStyle::Dashed => "divide-dashed",
DivideStyle::Dotted => "divide-dotted",
DivideStyle::Double => "divide-double",
DivideStyle::None => "divide-none",
}
}
}

View file

@ -5,6 +5,7 @@ use super::UIWidget;
pub mod animation;
pub mod aspect;
pub mod background;
pub mod border;
pub mod container;
pub mod cursor;
pub mod div;