Create ferris example to showcase ContentFit and Rotation
This commit is contained in:
parent
610394b695
commit
efc55b655b
5 changed files with 234 additions and 1 deletions
|
|
@ -7,6 +7,11 @@ use std::ops::{Add, AddAssign, Div, Mul, RangeInclusive, Sub, SubAssign};
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct Degrees(pub f32);
|
pub struct Degrees(pub f32);
|
||||||
|
|
||||||
|
impl Degrees {
|
||||||
|
/// The range of degrees of a circle.
|
||||||
|
pub const RANGE: RangeInclusive<Self> = Self(0.0)..=Self(360.0);
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialEq<f32> for Degrees {
|
impl PartialEq<f32> for Degrees {
|
||||||
fn eq(&self, other: &f32) -> bool {
|
fn eq(&self, other: &f32) -> bool {
|
||||||
self.0.eq(other)
|
self.0.eq(other)
|
||||||
|
|
@ -19,6 +24,44 @@ impl PartialOrd<f32> for Degrees {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<f32> for Degrees {
|
||||||
|
fn from(degrees: f32) -> Self {
|
||||||
|
Self(degrees)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Degrees {
|
||||||
|
fn from(degrees: u8) -> Self {
|
||||||
|
Self(f32::from(degrees))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Degrees> for f32 {
|
||||||
|
fn from(degrees: Degrees) -> Self {
|
||||||
|
degrees.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Degrees> for f64 {
|
||||||
|
fn from(degrees: Degrees) -> Self {
|
||||||
|
Self::from(degrees.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl num_traits::FromPrimitive for Degrees {
|
||||||
|
fn from_i64(n: i64) -> Option<Self> {
|
||||||
|
Some(Self(n as f32))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_u64(n: u64) -> Option<Self> {
|
||||||
|
Some(Self(n as f32))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_f64(n: f64) -> Option<Self> {
|
||||||
|
Some(Self(n as f32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Radians
|
/// Radians
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct Radians(pub f32);
|
pub struct Radians(pub f32);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
//! Control the fit of some content (like an image) within a space.
|
//! Control the fit of some content (like an image) within a space.
|
||||||
use crate::Size;
|
use crate::Size;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// The strategy used to fit the contents of a widget to its bounding box.
|
/// The strategy used to fit the contents of a widget to its bounding box.
|
||||||
///
|
///
|
||||||
/// Each variant of this enum is a strategy that can be applied for resolving
|
/// Each variant of this enum is a strategy that can be applied for resolving
|
||||||
|
|
@ -118,3 +120,15 @@ impl ContentFit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ContentFit {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(match self {
|
||||||
|
ContentFit::Contain => "Contain",
|
||||||
|
ContentFit::Cover => "Cover",
|
||||||
|
ContentFit::Fill => "Fill",
|
||||||
|
ContentFit::None => "None",
|
||||||
|
ContentFit::ScaleDown => "Scale Down",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! Control the rotation of some content (like an image) within a space.
|
//! Control the rotation of some content (like an image) within a space.
|
||||||
use crate::{Radians, Size};
|
use crate::{Degrees, Radians, Size};
|
||||||
|
|
||||||
/// The strategy used to rotate the content.
|
/// The strategy used to rotate the content.
|
||||||
///
|
///
|
||||||
|
|
@ -31,6 +31,11 @@ impl Rotation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the angle of the [`Rotation`] in [`Degrees`].
|
||||||
|
pub fn degrees(self) -> Degrees {
|
||||||
|
Degrees(self.radians().0.to_degrees())
|
||||||
|
}
|
||||||
|
|
||||||
/// Rotates the given [`Size`].
|
/// Rotates the given [`Size`].
|
||||||
pub fn apply(self, size: Size) -> Size {
|
pub fn apply(self, size: Size) -> Size {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
||||||
10
examples/ferris/Cargo.toml
Normal file
10
examples/ferris/Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "ferris"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
iced.workspace = true
|
||||||
|
iced.features = ["image"]
|
||||||
161
examples/ferris/src/main.rs
Normal file
161
examples/ferris/src/main.rs
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
use iced::widget::{column, container, image, pick_list, row, slider, text};
|
||||||
|
use iced::{
|
||||||
|
Alignment, Color, ContentFit, Degrees, Element, Length, Rotation, Theme,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn main() -> iced::Result {
|
||||||
|
iced::program("Ferris - Iced", Image::update, Image::view)
|
||||||
|
.theme(|_| Theme::TokyoNight)
|
||||||
|
.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Image {
|
||||||
|
width: f32,
|
||||||
|
rotation: Rotation,
|
||||||
|
content_fit: ContentFit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum Message {
|
||||||
|
WidthChanged(f32),
|
||||||
|
RotationStrategyChanged(RotationStrategy),
|
||||||
|
RotationChanged(Degrees),
|
||||||
|
ContentFitChanged(ContentFit),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image {
|
||||||
|
fn update(&mut self, message: Message) {
|
||||||
|
match message {
|
||||||
|
Message::WidthChanged(width) => {
|
||||||
|
self.width = width;
|
||||||
|
}
|
||||||
|
Message::RotationStrategyChanged(strategy) => {
|
||||||
|
self.rotation = match strategy {
|
||||||
|
RotationStrategy::Floating => {
|
||||||
|
Rotation::Floating(self.rotation.radians())
|
||||||
|
}
|
||||||
|
RotationStrategy::Solid => {
|
||||||
|
Rotation::Solid(self.rotation.radians())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Message::RotationChanged(rotation) => {
|
||||||
|
self.rotation = match self.rotation {
|
||||||
|
Rotation::Floating(_) => {
|
||||||
|
Rotation::Floating(rotation.into())
|
||||||
|
}
|
||||||
|
Rotation::Solid(_) => Rotation::Solid(rotation.into()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Message::ContentFitChanged(content_fit) => {
|
||||||
|
self.content_fit = content_fit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> Element<Message> {
|
||||||
|
let i_am_ferris = container(
|
||||||
|
column![
|
||||||
|
"Hello!",
|
||||||
|
Element::from(
|
||||||
|
image(format!(
|
||||||
|
"{}/../tour/images/ferris.png",
|
||||||
|
env!("CARGO_MANIFEST_DIR")
|
||||||
|
))
|
||||||
|
.width(self.width)
|
||||||
|
.content_fit(self.content_fit)
|
||||||
|
.rotation(self.rotation)
|
||||||
|
)
|
||||||
|
.explain(Color::WHITE),
|
||||||
|
"I am Ferris!"
|
||||||
|
]
|
||||||
|
.spacing(20)
|
||||||
|
.align_items(Alignment::Center),
|
||||||
|
)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.center_x()
|
||||||
|
.center_y();
|
||||||
|
|
||||||
|
let sizing = row![
|
||||||
|
pick_list(
|
||||||
|
[
|
||||||
|
ContentFit::Contain,
|
||||||
|
ContentFit::Cover,
|
||||||
|
ContentFit::Fill,
|
||||||
|
ContentFit::None,
|
||||||
|
ContentFit::ScaleDown
|
||||||
|
],
|
||||||
|
Some(self.content_fit),
|
||||||
|
Message::ContentFitChanged
|
||||||
|
)
|
||||||
|
.width(Length::Fill),
|
||||||
|
column![
|
||||||
|
slider(100.0..=500.0, self.width, Message::WidthChanged),
|
||||||
|
text(format!("Width: {}px", self.width))
|
||||||
|
.size(14)
|
||||||
|
.line_height(1.0)
|
||||||
|
]
|
||||||
|
.spacing(5)
|
||||||
|
.align_items(Alignment::Center)
|
||||||
|
]
|
||||||
|
.spacing(10);
|
||||||
|
|
||||||
|
let rotation = row![
|
||||||
|
pick_list(
|
||||||
|
[RotationStrategy::Floating, RotationStrategy::Solid],
|
||||||
|
Some(match self.rotation {
|
||||||
|
Rotation::Floating(_) => RotationStrategy::Floating,
|
||||||
|
Rotation::Solid(_) => RotationStrategy::Solid,
|
||||||
|
}),
|
||||||
|
Message::RotationStrategyChanged,
|
||||||
|
)
|
||||||
|
.width(Length::Fill),
|
||||||
|
column![
|
||||||
|
slider(
|
||||||
|
Degrees::RANGE,
|
||||||
|
self.rotation.degrees(),
|
||||||
|
Message::RotationChanged
|
||||||
|
),
|
||||||
|
text(format!(
|
||||||
|
"Rotation: {:.0}°",
|
||||||
|
f32::from(self.rotation.degrees())
|
||||||
|
))
|
||||||
|
.size(14)
|
||||||
|
.line_height(1.0)
|
||||||
|
]
|
||||||
|
.spacing(5)
|
||||||
|
.align_items(Alignment::Center)
|
||||||
|
]
|
||||||
|
.spacing(10);
|
||||||
|
|
||||||
|
container(column![i_am_ferris, sizing, rotation].spacing(10))
|
||||||
|
.padding(10)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Image {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
width: 300.0,
|
||||||
|
rotation: Rotation::default(),
|
||||||
|
content_fit: ContentFit::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum RotationStrategy {
|
||||||
|
Floating,
|
||||||
|
Solid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for RotationStrategy {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(match self {
|
||||||
|
Self::Floating => "Floating",
|
||||||
|
Self::Solid => "Solid",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue