use bevy::prelude::*;
use crate::theme::MaterialTheme;
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum DividerVariant {
#[default]
FullWidth,
Inset,
MiddleInset,
}
#[derive(Component)]
pub struct MaterialDivider {
pub variant: DividerVariant,
pub vertical: bool,
}
impl MaterialDivider {
pub fn new() -> Self {
Self {
variant: DividerVariant::default(),
vertical: false,
}
}
pub fn vertical() -> Self {
Self {
variant: DividerVariant::default(),
vertical: true,
}
}
pub fn with_variant(mut self, variant: DividerVariant) -> Self {
self.variant = variant;
self
}
pub fn inset(self) -> Self {
self.with_variant(DividerVariant::Inset)
}
pub fn middle_inset(self) -> Self {
self.with_variant(DividerVariant::MiddleInset)
}
pub fn color(&self, theme: &MaterialTheme) -> Color {
theme.outline_variant
}
}
impl Default for MaterialDivider {
fn default() -> Self {
Self::new()
}
}
pub const DIVIDER_THICKNESS: f32 = 1.0;
pub const DIVIDER_INSET: f32 = 16.0;
pub struct DividerBuilder {
divider: MaterialDivider,
}
impl DividerBuilder {
pub fn new() -> Self {
Self {
divider: MaterialDivider::new(),
}
}
pub fn vertical() -> Self {
Self {
divider: MaterialDivider::vertical(),
}
}
pub fn variant(mut self, variant: DividerVariant) -> Self {
self.divider.variant = variant;
self
}
pub fn full_width(self) -> Self {
self.variant(DividerVariant::FullWidth)
}
pub fn inset(self) -> Self {
self.variant(DividerVariant::Inset)
}
pub fn middle_inset(self) -> Self {
self.variant(DividerVariant::MiddleInset)
}
pub fn build(self, theme: &MaterialTheme) -> impl Bundle {
let color = self.divider.color(theme);
let is_vertical = self.divider.vertical;
let variant = self.divider.variant;
let margin = match variant {
DividerVariant::FullWidth => UiRect::ZERO,
DividerVariant::Inset => {
if is_vertical {
UiRect::top(Val::Px(DIVIDER_INSET))
} else {
UiRect::left(Val::Px(DIVIDER_INSET))
}
}
DividerVariant::MiddleInset => {
if is_vertical {
UiRect::vertical(Val::Px(DIVIDER_INSET))
} else {
UiRect::horizontal(Val::Px(DIVIDER_INSET))
}
}
};
(
self.divider,
Node {
width: if is_vertical {
Val::Px(DIVIDER_THICKNESS)
} else {
Val::Percent(100.0)
},
height: if is_vertical {
Val::Percent(100.0)
} else {
Val::Px(DIVIDER_THICKNESS)
},
margin,
..default()
},
BackgroundColor(color),
)
}
}
impl Default for DividerBuilder {
fn default() -> Self {
Self::new()
}
}
pub fn horizontal_divider(theme: &MaterialTheme) -> impl Bundle {
DividerBuilder::new().build(theme)
}
pub fn vertical_divider(theme: &MaterialTheme) -> impl Bundle {
DividerBuilder::vertical().build(theme)
}
pub fn inset_divider(theme: &MaterialTheme) -> impl Bundle {
DividerBuilder::new().inset().build(theme)
}
pub trait SpawnDividerChild {
fn spawn_horizontal_divider(&mut self, theme: &MaterialTheme);
fn spawn_vertical_divider(&mut self, theme: &MaterialTheme);
fn spawn_inset_divider(&mut self, theme: &MaterialTheme);
fn spawn_divider_with(&mut self, theme: &MaterialTheme, builder: DividerBuilder);
}
impl SpawnDividerChild for ChildSpawnerCommands<'_> {
fn spawn_horizontal_divider(&mut self, theme: &MaterialTheme) {
self.spawn(DividerBuilder::new().build(theme));
}
fn spawn_vertical_divider(&mut self, theme: &MaterialTheme) {
self.spawn(DividerBuilder::vertical().build(theme));
}
fn spawn_inset_divider(&mut self, theme: &MaterialTheme) {
self.spawn(DividerBuilder::new().inset().build(theme));
}
fn spawn_divider_with(&mut self, theme: &MaterialTheme, builder: DividerBuilder) {
self.spawn(builder.build(theme));
}
}