summaryrefslogblamecommitdiffstats
path: root/examples/ferris/src/main.rs
blob: b7536740af758c6f6d0285753e6be81ed070f4cc (plain) (tree)
1
2
3
4
5
6
7
8




                                                                     
           

                                                                              



                                                              
                                          







                                     

                       







                                              

                             




























                                                                           






















                                                                                




























































                                                                         
















                                                                            

















                                                                     

                                      

















                                                                        
use iced::time::Instant;
use iced::widget::{
    checkbox, column, container, image, pick_list, row, slider, text,
};
use iced::window;
use iced::{
    Alignment, Color, ContentFit, Degrees, Element, Length, Radians, Rotation,
    Subscription, Theme,
};

pub fn main() -> iced::Result {
    iced::program("Ferris - Iced", Image::update, Image::view)
        .subscription(Image::subscription)
        .theme(|_| Theme::TokyoNight)
        .run()
}

struct Image {
    width: f32,
    rotation: Rotation,
    content_fit: ContentFit,
    spin: bool,
    last_tick: Instant,
}

#[derive(Debug, Clone, Copy)]
enum Message {
    WidthChanged(f32),
    RotationStrategyChanged(RotationStrategy),
    RotationChanged(Degrees),
    ContentFitChanged(ContentFit),
    SpinToggled(bool),
    RedrawRequested(Instant),
}

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;
            }
            Message::SpinToggled(spin) => {
                self.spin = spin;
                self.last_tick = Instant::now();
            }
            Message::RedrawRequested(now) => {
                const ROTATION_SPEED: Degrees = Degrees(360.0);

                let delta = (now - self.last_tick).as_millis() as f32 / 1_000.0;

                *self.rotation.radians_mut() = (self.rotation.radians()
                    + ROTATION_SPEED * delta)
                    % (2.0 * Radians::PI);

                self.last_tick = now;
            }
        }
    }

    fn subscription(&self) -> Subscription<Message> {
        if self.spin {
            window::frames().map(Message::RedrawRequested)
        } else {
            Subscription::none()
        }
    }

    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),
            row![
                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),
                checkbox("Spin!", self.spin).on_toggle(Message::SpinToggled)
            ]
            .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(),
            spin: false,
            last_tick: Instant::now(),
        }
    }
}

#[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",
        })
    }
}