Skip to content

Commit efc55b6

Browse files
committed
Create ferris example to showcase ContentFit and Rotation
1 parent 610394b commit efc55b6

5 files changed

Lines changed: 234 additions & 1 deletion

File tree

core/src/angle.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ use std::ops::{Add, AddAssign, Div, Mul, RangeInclusive, Sub, SubAssign};
77
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
88
pub struct Degrees(pub f32);
99

10+
impl Degrees {
11+
/// The range of degrees of a circle.
12+
pub const RANGE: RangeInclusive<Self> = Self(0.0)..=Self(360.0);
13+
}
14+
1015
impl PartialEq<f32> for Degrees {
1116
fn eq(&self, other: &f32) -> bool {
1217
self.0.eq(other)
@@ -19,6 +24,44 @@ impl PartialOrd<f32> for Degrees {
1924
}
2025
}
2126

27+
impl From<f32> for Degrees {
28+
fn from(degrees: f32) -> Self {
29+
Self(degrees)
30+
}
31+
}
32+
33+
impl From<u8> for Degrees {
34+
fn from(degrees: u8) -> Self {
35+
Self(f32::from(degrees))
36+
}
37+
}
38+
39+
impl From<Degrees> for f32 {
40+
fn from(degrees: Degrees) -> Self {
41+
degrees.0
42+
}
43+
}
44+
45+
impl From<Degrees> for f64 {
46+
fn from(degrees: Degrees) -> Self {
47+
Self::from(degrees.0)
48+
}
49+
}
50+
51+
impl num_traits::FromPrimitive for Degrees {
52+
fn from_i64(n: i64) -> Option<Self> {
53+
Some(Self(n as f32))
54+
}
55+
56+
fn from_u64(n: u64) -> Option<Self> {
57+
Some(Self(n as f32))
58+
}
59+
60+
fn from_f64(n: f64) -> Option<Self> {
61+
Some(Self(n as f32))
62+
}
63+
}
64+
2265
/// Radians
2366
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
2467
pub struct Radians(pub f32);

core/src/content_fit.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Control the fit of some content (like an image) within a space.
22
use crate::Size;
33

4+
use std::fmt;
5+
46
/// The strategy used to fit the contents of a widget to its bounding box.
57
///
68
/// Each variant of this enum is a strategy that can be applied for resolving
@@ -118,3 +120,15 @@ impl ContentFit {
118120
}
119121
}
120122
}
123+
124+
impl fmt::Display for ContentFit {
125+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126+
f.write_str(match self {
127+
ContentFit::Contain => "Contain",
128+
ContentFit::Cover => "Cover",
129+
ContentFit::Fill => "Fill",
130+
ContentFit::None => "None",
131+
ContentFit::ScaleDown => "Scale Down",
132+
})
133+
}
134+
}

core/src/rotation.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Control the rotation of some content (like an image) within a space.
2-
use crate::{Radians, Size};
2+
use crate::{Degrees, Radians, Size};
33

44
/// The strategy used to rotate the content.
55
///
@@ -31,6 +31,11 @@ impl Rotation {
3131
}
3232
}
3333

34+
/// Returns the angle of the [`Rotation`] in [`Degrees`].
35+
pub fn degrees(self) -> Degrees {
36+
Degrees(self.radians().0.to_degrees())
37+
}
38+
3439
/// Rotates the given [`Size`].
3540
pub fn apply(self, size: Size) -> Size {
3641
match self {

examples/ferris/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "ferris"
3+
version = "0.1.0"
4+
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
5+
edition = "2021"
6+
publish = false
7+
8+
[dependencies]
9+
iced.workspace = true
10+
iced.features = ["image"]

examples/ferris/src/main.rs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
use iced::widget::{column, container, image, pick_list, row, slider, text};
2+
use iced::{
3+
Alignment, Color, ContentFit, Degrees, Element, Length, Rotation, Theme,
4+
};
5+
6+
pub fn main() -> iced::Result {
7+
iced::program("Ferris - Iced", Image::update, Image::view)
8+
.theme(|_| Theme::TokyoNight)
9+
.run()
10+
}
11+
12+
struct Image {
13+
width: f32,
14+
rotation: Rotation,
15+
content_fit: ContentFit,
16+
}
17+
18+
#[derive(Debug, Clone, Copy)]
19+
enum Message {
20+
WidthChanged(f32),
21+
RotationStrategyChanged(RotationStrategy),
22+
RotationChanged(Degrees),
23+
ContentFitChanged(ContentFit),
24+
}
25+
26+
impl Image {
27+
fn update(&mut self, message: Message) {
28+
match message {
29+
Message::WidthChanged(width) => {
30+
self.width = width;
31+
}
32+
Message::RotationStrategyChanged(strategy) => {
33+
self.rotation = match strategy {
34+
RotationStrategy::Floating => {
35+
Rotation::Floating(self.rotation.radians())
36+
}
37+
RotationStrategy::Solid => {
38+
Rotation::Solid(self.rotation.radians())
39+
}
40+
};
41+
}
42+
Message::RotationChanged(rotation) => {
43+
self.rotation = match self.rotation {
44+
Rotation::Floating(_) => {
45+
Rotation::Floating(rotation.into())
46+
}
47+
Rotation::Solid(_) => Rotation::Solid(rotation.into()),
48+
};
49+
}
50+
Message::ContentFitChanged(content_fit) => {
51+
self.content_fit = content_fit;
52+
}
53+
}
54+
}
55+
56+
fn view(&self) -> Element<Message> {
57+
let i_am_ferris = container(
58+
column![
59+
"Hello!",
60+
Element::from(
61+
image(format!(
62+
"{}/../tour/images/ferris.png",
63+
env!("CARGO_MANIFEST_DIR")
64+
))
65+
.width(self.width)
66+
.content_fit(self.content_fit)
67+
.rotation(self.rotation)
68+
)
69+
.explain(Color::WHITE),
70+
"I am Ferris!"
71+
]
72+
.spacing(20)
73+
.align_items(Alignment::Center),
74+
)
75+
.width(Length::Fill)
76+
.height(Length::Fill)
77+
.center_x()
78+
.center_y();
79+
80+
let sizing = row![
81+
pick_list(
82+
[
83+
ContentFit::Contain,
84+
ContentFit::Cover,
85+
ContentFit::Fill,
86+
ContentFit::None,
87+
ContentFit::ScaleDown
88+
],
89+
Some(self.content_fit),
90+
Message::ContentFitChanged
91+
)
92+
.width(Length::Fill),
93+
column![
94+
slider(100.0..=500.0, self.width, Message::WidthChanged),
95+
text(format!("Width: {}px", self.width))
96+
.size(14)
97+
.line_height(1.0)
98+
]
99+
.spacing(5)
100+
.align_items(Alignment::Center)
101+
]
102+
.spacing(10);
103+
104+
let rotation = row![
105+
pick_list(
106+
[RotationStrategy::Floating, RotationStrategy::Solid],
107+
Some(match self.rotation {
108+
Rotation::Floating(_) => RotationStrategy::Floating,
109+
Rotation::Solid(_) => RotationStrategy::Solid,
110+
}),
111+
Message::RotationStrategyChanged,
112+
)
113+
.width(Length::Fill),
114+
column![
115+
slider(
116+
Degrees::RANGE,
117+
self.rotation.degrees(),
118+
Message::RotationChanged
119+
),
120+
text(format!(
121+
"Rotation: {:.0}°",
122+
f32::from(self.rotation.degrees())
123+
))
124+
.size(14)
125+
.line_height(1.0)
126+
]
127+
.spacing(5)
128+
.align_items(Alignment::Center)
129+
]
130+
.spacing(10);
131+
132+
container(column![i_am_ferris, sizing, rotation].spacing(10))
133+
.padding(10)
134+
.into()
135+
}
136+
}
137+
138+
impl Default for Image {
139+
fn default() -> Self {
140+
Self {
141+
width: 300.0,
142+
rotation: Rotation::default(),
143+
content_fit: ContentFit::default(),
144+
}
145+
}
146+
}
147+
148+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
149+
enum RotationStrategy {
150+
Floating,
151+
Solid,
152+
}
153+
154+
impl std::fmt::Display for RotationStrategy {
155+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156+
f.write_str(match self {
157+
Self::Floating => "Floating",
158+
Self::Solid => "Solid",
159+
})
160+
}
161+
}

0 commit comments

Comments
 (0)