use crate::node::ImageFormat;
use crate::units::Pt;
pub use crate::color::Color;
#[derive(Debug, Clone, PartialEq)]
pub struct VisualStyle {
pub background_color: Option<Color>,
pub background_image: Option<BackgroundImage>,
pub background_gradient: Option<Gradient>,
pub box_shadows: Vec<BoxShadow>,
pub opacity: f32,
pub border_top: BorderSide,
pub border_right: BorderSide,
pub border_bottom: BorderSide,
pub border_left: BorderSide,
pub border_radius_top_left: Pt,
pub border_radius_top_right: Pt,
pub border_radius_bottom_right: Pt,
pub border_radius_bottom_left: Pt,
pub border_radius_top_left_ry: Pt,
pub border_radius_top_right_ry: Pt,
pub border_radius_bottom_right_ry: Pt,
pub border_radius_bottom_left_ry: Pt,
}
#[derive(Debug, Clone, PartialEq)]
pub struct BackgroundImage {
pub data: Vec<u8>,
pub format: ImageFormat,
pub size: BackgroundSize,
pub position_x: BackgroundPosition,
pub position_y: BackgroundPosition,
pub repeat: BackgroundRepeat,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BackgroundRepeat {
#[default]
NoRepeat,
RepeatX,
RepeatY,
Repeat,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Gradient {
Linear(LinearGradient),
Radial(RadialGradient),
}
#[derive(Debug, Clone, PartialEq)]
pub struct LinearGradient {
pub angle_degrees: f64,
pub stops: Vec<GradientStop>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct RadialGradient {
pub center_x: f64,
pub center_y: f64,
pub radius: f64,
pub stops: Vec<GradientStop>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GradientStop {
pub position: f32,
pub color: Color,
}
#[derive(Debug, Clone, PartialEq)]
pub struct BoxShadow {
pub offset_x: Pt,
pub offset_y: Pt,
pub blur_radius: Pt,
pub spread_radius: Pt,
pub color: Color,
pub inset: bool,
}
impl BoxShadow {
#[must_use]
pub fn drop_shadow(offset_x: Pt, offset_y: Pt, blur: Pt, color: Color) -> Self {
Self {
offset_x,
offset_y,
blur_radius: blur,
spread_radius: Pt::ZERO,
color,
inset: false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum BackgroundSize {
#[default]
Cover,
Contain,
Auto,
Explicit {
width: Option<Pt>,
height: Option<Pt>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum BackgroundPosition {
#[default]
Start,
Center,
End,
Length(Pt),
}
impl Default for VisualStyle {
fn default() -> Self {
Self {
background_color: None,
background_image: None,
background_gradient: None,
box_shadows: Vec::new(),
opacity: 1.0,
border_top: BorderSide::NONE,
border_right: BorderSide::NONE,
border_bottom: BorderSide::NONE,
border_left: BorderSide::NONE,
border_radius_top_left: Pt::ZERO,
border_radius_top_right: Pt::ZERO,
border_radius_bottom_right: Pt::ZERO,
border_radius_bottom_left: Pt::ZERO,
border_radius_top_left_ry: Pt::ZERO,
border_radius_top_right_ry: Pt::ZERO,
border_radius_bottom_right_ry: Pt::ZERO,
border_radius_bottom_left_ry: Pt::ZERO,
}
}
}
impl VisualStyle {
#[must_use]
pub fn has_border_radius(&self) -> bool {
self.border_radius_top_left.get() > 0.0
|| self.border_radius_top_right.get() > 0.0
|| self.border_radius_bottom_right.get() > 0.0
|| self.border_radius_bottom_left.get() > 0.0
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BorderSide {
pub width: Pt,
pub style: BorderStyle,
pub color: Color,
}
impl BorderSide {
pub const NONE: Self = Self {
width: Pt::ZERO,
style: BorderStyle::None,
color: Color::BLACK,
};
#[must_use]
pub fn is_visible(&self) -> bool {
self.width.get() > 0.0 && self.style != BorderStyle::None
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum BorderStyle {
#[default]
None,
Solid,
Dashed,
Dotted,
}