1use crate::{Color, DashStyle};
2
3#[derive(Debug, Clone)]
5pub struct BorderSide {
6 pub color: Color,
8 pub width: f32,
10 pub dash_style: DashStyle,
12}
13
14impl BorderSide {
15 pub fn new(color: Color, width: f32, dash_style: DashStyle) -> Self {
17 Self {
18 color,
19 width,
20 dash_style,
21 }
22 }
23
24 pub fn solid(color: Color, width: f32) -> Self {
26 Self::new(color, width, DashStyle::Solid)
27 }
28
29 pub fn dashed(color: Color, width: f32, dash_style: DashStyle) -> Self {
31 Self::new(color, width, dash_style)
32 }
33
34 pub fn none() -> Self {
36 Self::new(Color::TRANSPARENT, 0.0, DashStyle::Solid)
37 }
38}
39
40impl Default for BorderSide {
41 fn default() -> Self {
42 Self::solid(Color::BLACK, 1.0)
43 }
44}
45
46#[derive(Debug, Clone)]
48pub struct Border {
49 pub top: BorderSide,
51 pub right: BorderSide,
53 pub bottom: BorderSide,
55 pub left: BorderSide,
57}
58
59impl Border {
60 pub fn new(top: BorderSide, right: BorderSide, bottom: BorderSide, left: BorderSide) -> Self {
62 Self {
63 top,
64 right,
65 bottom,
66 left,
67 }
68 }
69
70 pub fn all(side: BorderSide) -> Self {
72 Self {
73 top: side.clone(),
74 right: side.clone(),
75 bottom: side.clone(),
76 left: side,
77 }
78 }
79
80 pub fn symmetric(vertical: BorderSide, horizontal: BorderSide) -> Self {
82 Self {
83 top: vertical.clone(),
84 bottom: vertical,
85 left: horizontal.clone(),
86 right: horizontal,
87 }
88 }
89
90 pub fn solid(color: Color, width: f32) -> Self {
92 Self::all(BorderSide::solid(color, width))
93 }
94
95 pub fn dashed(color: Color, width: f32, dash_style: DashStyle) -> Self {
97 Self::all(BorderSide::dashed(color, width, dash_style))
98 }
99}
100
101impl Default for Border {
102 fn default() -> Self {
103 Self::solid(Color::BLACK, 1.0)
104 }
105}
106
107#[derive(Debug, Clone, Copy)]
109pub struct BorderRadius {
110 pub top_left: f32,
112 pub top_right: f32,
114 pub bottom_right: f32,
116 pub bottom_left: f32,
118}
119
120impl BorderRadius {
121 pub fn new(top_left: f32, top_right: f32, bottom_right: f32, bottom_left: f32) -> Self {
123 Self {
124 top_left,
125 top_right,
126 bottom_right,
127 bottom_left,
128 }
129 }
130
131 pub fn all(radius: f32) -> Self {
133 Self {
134 top_left: radius,
135 top_right: radius,
136 bottom_right: radius,
137 bottom_left: radius,
138 }
139 }
140
141 pub fn symmetric(diagonal1: f32, diagonal2: f32) -> Self {
143 Self {
144 top_left: diagonal1,
145 bottom_right: diagonal1,
146 top_right: diagonal2,
147 bottom_left: diagonal2,
148 }
149 }
150
151 pub fn zero() -> Self {
153 Self::all(0.0)
154 }
155
156 pub fn is_zero(&self) -> bool {
158 self.top_left == 0.0
159 && self.top_right == 0.0
160 && self.bottom_right == 0.0
161 && self.bottom_left == 0.0
162 }
163
164 pub fn clamp(&self, max_width: f32, max_height: f32) -> Self {
166 let max_radius_w = max_width / 2.0;
167 let max_radius_h = max_height / 2.0;
168 let max_radius = max_radius_w.min(max_radius_h);
169
170 Self {
171 top_left: self.top_left.min(max_radius).max(0.0),
172 top_right: self.top_right.min(max_radius).max(0.0),
173 bottom_right: self.bottom_right.min(max_radius).max(0.0),
174 bottom_left: self.bottom_left.min(max_radius).max(0.0),
175 }
176 }
177}
178
179impl Default for BorderRadius {
180 fn default() -> Self {
181 Self::zero()
182 }
183}