Skip to content

Commit ab392ce

Browse files
committed
Improve Border ergonomics
1 parent 7c33417 commit ab392ce

13 files changed

Lines changed: 204 additions & 95 deletions

File tree

core/src/border.rs

Lines changed: 136 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,64 @@ pub struct Border {
1010
/// The width of the border.
1111
pub width: f32,
1212

13-
/// The radius of the border.
13+
/// The [`Radius`] of the border.
1414
pub radius: Radius,
1515
}
1616

17-
impl Border {
18-
/// Creates a new default rounded [`Border`] with the given [`Radius`].
19-
///
20-
/// ```
21-
/// # use iced_core::Border;
22-
/// #
23-
/// assert_eq!(Border::rounded(10), Border::default().with_radius(10));
24-
/// ```
25-
pub fn rounded(radius: impl Into<Radius>) -> Self {
26-
Self::default().with_radius(radius)
27-
}
17+
/// Creates a new [`Border`] with the given [`Radius`].
18+
///
19+
/// ```
20+
/// # use iced_core::border::{self, Border};
21+
/// #
22+
/// assert_eq!(border::rounded(10), Border::default().rounded(10));
23+
/// ```
24+
pub fn rounded(radius: impl Into<Radius>) -> Border {
25+
Border::default().rounded(radius)
26+
}
27+
28+
/// Creates a new [`Border`] with the given [`Color`].
29+
///
30+
/// ```
31+
/// # use iced_core::border::{self, Border};
32+
/// # use iced_core::Color;
33+
/// #
34+
/// assert_eq!(border::color(Color::BLACK), Border::default().color(Color::BLACK));
35+
/// ```
36+
pub fn color(color: impl Into<Color>) -> Border {
37+
Border::default().color(color)
38+
}
39+
40+
/// Creates a new [`Border`] with the given `width`.
41+
///
42+
/// ```
43+
/// # use iced_core::border::{self, Border};
44+
/// # use iced_core::Color;
45+
/// #
46+
/// assert_eq!(border::width(10), Border::default().width(10));
47+
/// ```
48+
pub fn width(width: impl Into<Pixels>) -> Border {
49+
Border::default().width(width)
50+
}
2851

29-
/// Updates the [`Color`] of the [`Border`].
30-
pub fn with_color(self, color: impl Into<Color>) -> Self {
52+
impl Border {
53+
/// Sets the [`Color`] of the [`Border`].
54+
pub fn color(self, color: impl Into<Color>) -> Self {
3155
Self {
3256
color: color.into(),
3357
..self
3458
}
3559
}
3660

37-
/// Updates the [`Radius`] of the [`Border`].
38-
pub fn with_radius(self, radius: impl Into<Radius>) -> Self {
61+
/// Sets the [`Radius`] of the [`Border`].
62+
pub fn rounded(self, radius: impl Into<Radius>) -> Self {
3963
Self {
4064
radius: radius.into(),
4165
..self
4266
}
4367
}
4468

45-
/// Updates the width of the [`Border`].
46-
pub fn with_width(self, width: impl Into<Pixels>) -> Self {
69+
/// Sets the width of the [`Border`].
70+
pub fn width(self, width: impl Into<Pixels>) -> Self {
4771
Self {
4872
width: width.into().0,
4973
..self
@@ -54,11 +78,96 @@ impl Border {
5478
/// The border radii for the corners of a graphics primitive in the order:
5579
/// top-left, top-right, bottom-right, bottom-left.
5680
#[derive(Debug, Clone, Copy, PartialEq, Default)]
57-
pub struct Radius([f32; 4]);
81+
pub struct Radius {
82+
/// Top left radius
83+
pub top_left: f32,
84+
/// Top right radius
85+
pub top_right: f32,
86+
/// Bottom right radius
87+
pub bottom_right: f32,
88+
/// Bottom left radius
89+
pub bottom_left: f32,
90+
}
91+
92+
/// Creates a new [`Radius`] with the same value for each corner.
93+
pub fn radius(value: impl Into<Pixels>) -> Radius {
94+
Radius::new(value)
95+
}
96+
97+
/// Creates a new [`Radius`] with the given top left value.
98+
pub fn top_left(value: impl Into<Pixels>) -> Radius {
99+
Radius::default().top_left(value)
100+
}
101+
102+
/// Creates a new [`Radius`] with the given top right value.
103+
pub fn top_right(value: impl Into<Pixels>) -> Radius {
104+
Radius::default().top_right(value)
105+
}
106+
107+
/// Creates a new [`Radius`] with the given bottom right value.
108+
pub fn bottom_right(value: impl Into<Pixels>) -> Radius {
109+
Radius::default().bottom_right(value)
110+
}
111+
112+
/// Creates a new [`Radius`] with the given bottom left value.
113+
pub fn bottom_left(value: impl Into<Pixels>) -> Radius {
114+
Radius::default().bottom_left(value)
115+
}
116+
117+
impl Radius {
118+
/// Creates a new [`Radius`] with the same value for each corner.
119+
pub fn new(value: impl Into<Pixels>) -> Self {
120+
let value = value.into().0;
121+
122+
Self {
123+
top_left: value,
124+
top_right: value,
125+
bottom_right: value,
126+
bottom_left: value,
127+
}
128+
}
129+
130+
/// Sets the top left value of the [`Radius`].
131+
pub fn top_left(self, value: impl Into<Pixels>) -> Self {
132+
Self {
133+
top_left: value.into().0,
134+
..self
135+
}
136+
}
137+
138+
/// Sets the top right value of the [`Radius`].
139+
pub fn top_right(self, value: impl Into<Pixels>) -> Self {
140+
Self {
141+
top_right: value.into().0,
142+
..self
143+
}
144+
}
145+
146+
/// Sets the bottom right value of the [`Radius`].
147+
pub fn bottom_right(self, value: impl Into<Pixels>) -> Self {
148+
Self {
149+
bottom_right: value.into().0,
150+
..self
151+
}
152+
}
153+
154+
/// Sets the bottom left value of the [`Radius`].
155+
pub fn bottom_left(self, value: impl Into<Pixels>) -> Self {
156+
Self {
157+
bottom_left: value.into().0,
158+
..self
159+
}
160+
}
161+
}
58162

59163
impl From<f32> for Radius {
60-
fn from(w: f32) -> Self {
61-
Self([w; 4])
164+
fn from(radius: f32) -> Self {
165+
Self {
166+
top_left: radius,
167+
top_right: radius,
168+
bottom_right: radius,
169+
bottom_left: radius,
170+
}
62171
}
63172
}
64173

@@ -80,14 +189,13 @@ impl From<i32> for Radius {
80189
}
81190
}
82191

83-
impl From<[f32; 4]> for Radius {
84-
fn from(radi: [f32; 4]) -> Self {
85-
Self(radi)
86-
}
87-
}
88-
89192
impl From<Radius> for [f32; 4] {
90193
fn from(radi: Radius) -> Self {
91-
radi.0
194+
[
195+
radi.top_left,
196+
radi.top_right,
197+
radi.bottom_right,
198+
radi.bottom_left,
199+
]
92200
}
93201
}

core/src/padding.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::{Pixels, Size};
3232
/// let widget = Widget::new().padding(20); // 20px on all sides
3333
/// let widget = Widget::new().padding([10, 20]); // top/bottom, left/right
3434
/// ```
35-
#[derive(Debug, Copy, Clone)]
35+
#[derive(Debug, Copy, Clone, Default)]
3636
pub struct Padding {
3737
/// Top padding
3838
pub top: f32,
@@ -51,34 +51,22 @@ pub fn all(padding: impl Into<Pixels>) -> Padding {
5151

5252
/// Create some top [`Padding`].
5353
pub fn top(padding: impl Into<Pixels>) -> Padding {
54-
Padding {
55-
top: padding.into().0,
56-
..Padding::ZERO
57-
}
54+
Padding::default().top(padding)
5855
}
5956

6057
/// Create some bottom [`Padding`].
6158
pub fn bottom(padding: impl Into<Pixels>) -> Padding {
62-
Padding {
63-
bottom: padding.into().0,
64-
..Padding::ZERO
65-
}
59+
Padding::default().bottom(padding)
6660
}
6761

6862
/// Create some left [`Padding`].
6963
pub fn left(padding: impl Into<Pixels>) -> Padding {
70-
Padding {
71-
left: padding.into().0,
72-
..Padding::ZERO
73-
}
64+
Padding::default().left(padding)
7465
}
7566

7667
/// Create some right [`Padding`].
7768
pub fn right(padding: impl Into<Pixels>) -> Padding {
78-
Padding {
79-
right: padding.into().0,
80-
..Padding::ZERO
81-
}
69+
Padding::default().right(padding)
8270
}
8371

8472
impl Padding {

examples/custom_quad/src/main.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@ mod quad {
33
use iced::advanced::layout::{self, Layout};
44
use iced::advanced::renderer;
55
use iced::advanced::widget::{self, Widget};
6+
use iced::border;
67
use iced::mouse;
78
use iced::{Border, Color, Element, Length, Rectangle, Shadow, Size};
89

910
pub struct CustomQuad {
1011
size: f32,
11-
radius: [f32; 4],
12+
radius: border::Radius,
1213
border_width: f32,
1314
shadow: Shadow,
1415
}
1516

1617
impl CustomQuad {
1718
pub fn new(
1819
size: f32,
19-
radius: [f32; 4],
20+
radius: border::Radius,
2021
border_width: f32,
2122
shadow: Shadow,
2223
) -> Self {
@@ -63,7 +64,7 @@ mod quad {
6364
renderer::Quad {
6465
bounds: layout.bounds(),
6566
border: Border {
66-
radius: self.radius.into(),
67+
radius: self.radius,
6768
width: self.border_width,
6869
color: Color::from_rgb(1.0, 0.0, 0.0),
6970
},
@@ -81,6 +82,7 @@ mod quad {
8182
}
8283
}
8384

85+
use iced::border;
8486
use iced::widget::{center, column, slider, text};
8587
use iced::{Center, Color, Element, Shadow, Vector};
8688

@@ -89,7 +91,7 @@ pub fn main() -> iced::Result {
8991
}
9092

9193
struct Example {
92-
radius: [f32; 4],
94+
radius: border::Radius,
9395
border_width: f32,
9496
shadow: Shadow,
9597
}
@@ -110,7 +112,7 @@ enum Message {
110112
impl Example {
111113
fn new() -> Self {
112114
Self {
113-
radius: [50.0; 4],
115+
radius: border::radius(50),
114116
border_width: 0.0,
115117
shadow: Shadow {
116118
color: Color::from_rgba(0.0, 0.0, 0.0, 0.8),
@@ -121,19 +123,18 @@ impl Example {
121123
}
122124

123125
fn update(&mut self, message: Message) {
124-
let [tl, tr, br, bl] = self.radius;
125126
match message {
126127
Message::RadiusTopLeftChanged(radius) => {
127-
self.radius = [radius, tr, br, bl];
128+
self.radius = self.radius.top_left(radius);
128129
}
129130
Message::RadiusTopRightChanged(radius) => {
130-
self.radius = [tl, radius, br, bl];
131+
self.radius = self.radius.top_right(radius);
131132
}
132133
Message::RadiusBottomRightChanged(radius) => {
133-
self.radius = [tl, tr, radius, bl];
134+
self.radius = self.radius.bottom_right(radius);
134135
}
135136
Message::RadiusBottomLeftChanged(radius) => {
136-
self.radius = [tl, tr, br, radius];
137+
self.radius = self.radius.bottom_left(radius);
137138
}
138139
Message::BorderWidthChanged(width) => {
139140
self.border_width = width;
@@ -151,7 +152,13 @@ impl Example {
151152
}
152153

153154
fn view(&self) -> Element<Message> {
154-
let [tl, tr, br, bl] = self.radius;
155+
let border::Radius {
156+
top_left,
157+
top_right,
158+
bottom_right,
159+
bottom_left,
160+
} = self.radius;
161+
155162
let Shadow {
156163
offset: Vector { x: sx, y: sy },
157164
blur_radius: sr,
@@ -165,12 +172,12 @@ impl Example {
165172
self.border_width,
166173
self.shadow
167174
),
168-
text!("Radius: {tl:.2}/{tr:.2}/{br:.2}/{bl:.2}"),
169-
slider(1.0..=100.0, tl, Message::RadiusTopLeftChanged).step(0.01),
170-
slider(1.0..=100.0, tr, Message::RadiusTopRightChanged).step(0.01),
171-
slider(1.0..=100.0, br, Message::RadiusBottomRightChanged)
175+
text!("Radius: {top_left:.2}/{top_right:.2}/{bottom_right:.2}/{bottom_left:.2}"),
176+
slider(1.0..=100.0, top_left, Message::RadiusTopLeftChanged).step(0.01),
177+
slider(1.0..=100.0, top_right, Message::RadiusTopRightChanged).step(0.01),
178+
slider(1.0..=100.0, bottom_right, Message::RadiusBottomRightChanged)
172179
.step(0.01),
173-
slider(1.0..=100.0, bl, Message::RadiusBottomLeftChanged)
180+
slider(1.0..=100.0, bottom_left, Message::RadiusBottomLeftChanged)
174181
.step(0.01),
175182
slider(1.0..=10.0, self.border_width, Message::BorderWidthChanged)
176183
.step(0.01),

examples/custom_widget/src/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ mod circle {
1212
use iced::advanced::layout::{self, Layout};
1313
use iced::advanced::renderer;
1414
use iced::advanced::widget::{self, Widget};
15+
use iced::border;
1516
use iced::mouse;
16-
use iced::{Border, Color, Element, Length, Rectangle, Size};
17+
use iced::{Color, Element, Length, Rectangle, Size};
1718

1819
pub struct Circle {
1920
radius: f32,
@@ -62,7 +63,7 @@ mod circle {
6263
renderer.fill_quad(
6364
renderer::Quad {
6465
bounds: layout.bounds(),
65-
border: Border::rounded(self.radius),
66+
border: border::rounded(self.radius),
6667
..renderer::Quad::default()
6768
},
6869
Color::BLACK,

0 commit comments

Comments
 (0)