diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/README.md | 2 | ||||
| -rw-r--r-- | examples/bezier_tool/src/main.rs | 5 | ||||
| -rw-r--r-- | examples/download_progress/Cargo.toml | 12 | ||||
| -rw-r--r-- | examples/download_progress/README.md | 17 | ||||
| -rw-r--r-- | examples/download_progress/src/download.rs | 112 | ||||
| -rw-r--r-- | examples/download_progress/src/main.rs | 143 | ||||
| -rw-r--r-- | examples/geometry/src/main.rs | 4 | ||||
| -rw-r--r-- | examples/integration/src/main.rs | 16 | ||||
| -rw-r--r-- | examples/pane_grid/Cargo.toml | 9 | ||||
| -rw-r--r-- | examples/pane_grid/README.md | 28 | ||||
| -rw-r--r-- | examples/pane_grid/src/main.rs | 306 | ||||
| -rw-r--r-- | examples/pokedex/Cargo.toml | 14 | ||||
| -rw-r--r-- | examples/styling/src/main.rs | 1 | ||||
| -rw-r--r-- | examples/svg/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/svg/src/main.rs | 11 | 
15 files changed, 660 insertions, 21 deletions
diff --git a/examples/README.md b/examples/README.md index 04399b93..5aea51eb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -73,9 +73,11 @@ A bunch of simpler examples exist:  - [`clock`](clock), an application that uses the `Canvas` widget to draw a clock and its hands to display the current time.  - [`counter`](counter), the classic counter example explained in the [`README`](../README.md).  - [`custom_widget`](custom_widget), a demonstration of how to build a custom widget that draws a circle. +- [`download_progress`](download_progress), a basic application that asynchronously downloads a dummy file of 100 MB and tracks the download progress.  - [`events`](events), a log of native events displayed using a conditional `Subscription`.  - [`geometry`](geometry), a custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [`iced_wgpu`](../wgpu).  - [`integration`](integration), a demonstration of how to integrate Iced in an existing graphical application. +- [`pane_grid`](pane_grid), a grid of panes that can be split, resized, and reorganized.  - [`pokedex`](pokedex), an application that displays a random Pokédex entry (sprite included!) by using the [PokéAPI].  - [`progress_bar`](progress_bar), a simple progress bar that can be filled by using a slider.  - [`solar_system`](solar_system), an animated solar system drawn using the `Canvas` widget and showcasing how to compose different transforms. diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index 023eb0f7..c3fbf276 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -23,7 +23,6 @@ mod bezier {          basic_shapes, BuffersBuilder, StrokeAttributes, StrokeOptions,          StrokeTessellator, VertexBuffers,      }; -    use std::sync::Arc;      pub struct Bezier<'a, Message> {          state: &'a mut State, @@ -175,10 +174,10 @@ mod bezier {              let mesh = Primitive::Mesh2D {                  origin: Point::new(bounds.x, bounds.y), -                buffers: Arc::new(Mesh2D { +                buffers: Mesh2D {                      vertices: buffer.vertices,                      indices: buffer.indices, -                }), +                },              };              ( diff --git a/examples/download_progress/Cargo.toml b/examples/download_progress/Cargo.toml new file mode 100644 index 00000000..34e6a132 --- /dev/null +++ b/examples/download_progress/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "download_progress" +version = "0.1.0" +authors = ["Songtronix <contact@songtronix.com>"] +edition = "2018" +publish = false + +[dependencies] +iced = { path = "../..", features = ["tokio"] } +iced_native = { path = "../../native" } +iced_futures = { path = "../../futures" } +reqwest = "0.10" diff --git a/examples/download_progress/README.md b/examples/download_progress/README.md new file mode 100644 index 00000000..c606c5f9 --- /dev/null +++ b/examples/download_progress/README.md @@ -0,0 +1,17 @@ +## Download progress + +A basic application that asynchronously downloads a dummy file of 100 MB and tracks the download progress. + +The example implements a custom `Subscription` in the __[`download`](src/download.rs)__ module. This subscription downloads and produces messages that can be used to keep track of its progress. + +<div align="center"> +  <a href="https://gfycat.com/wildearlyafricanwilddog"> +    <img src="https://thumbs.gfycat.com/WildEarlyAfricanwilddog-small.gif"> +  </a> +</div> + +You can run it with `cargo run`: + +``` +cargo run --package download_progress +``` diff --git a/examples/download_progress/src/download.rs b/examples/download_progress/src/download.rs new file mode 100644 index 00000000..f46a01f7 --- /dev/null +++ b/examples/download_progress/src/download.rs @@ -0,0 +1,112 @@ +use iced_futures::futures; + +// Just a little utility function +pub fn file<T: ToString>(url: T) -> iced::Subscription<Progress> { +    iced::Subscription::from_recipe(Download { +        url: url.to_string(), +    }) +} + +pub struct Download { +    url: String, +} + +// Make sure iced can use our download stream +impl<H, I> iced_native::subscription::Recipe<H, I> for Download +where +    H: std::hash::Hasher, +{ +    type Output = Progress; + +    fn hash(&self, state: &mut H) { +        use std::hash::Hash; + +        std::any::TypeId::of::<Self>().hash(state); +        self.url.hash(state); +    } + +    fn stream( +        self: Box<Self>, +        _input: futures::stream::BoxStream<'static, I>, +    ) -> futures::stream::BoxStream<'static, Self::Output> { +        Box::pin(futures::stream::unfold( +            State::Ready(self.url), +            |state| async move { +                match state { +                    State::Ready(url) => { +                        let response = reqwest::get(&url).await; + +                        match response { +                            Ok(response) => { +                                if let Some(total) = response.content_length() { +                                    Some(( +                                        Progress::Started, +                                        State::Downloading { +                                            response, +                                            total, +                                            downloaded: 0, +                                        }, +                                    )) +                                } else { +                                    Some((Progress::Errored, State::Finished)) +                                } +                            } +                            Err(_) => { +                                Some((Progress::Errored, State::Finished)) +                            } +                        } +                    } +                    State::Downloading { +                        mut response, +                        total, +                        downloaded, +                    } => match response.chunk().await { +                        Ok(Some(chunk)) => { +                            let downloaded = downloaded + chunk.len() as u64; + +                            let percentage = +                                (downloaded as f32 / total as f32) * 100.0; + +                            Some(( +                                Progress::Advanced(percentage), +                                State::Downloading { +                                    response, +                                    total, +                                    downloaded, +                                }, +                            )) +                        } +                        Ok(None) => Some((Progress::Finished, State::Finished)), +                        Err(_) => Some((Progress::Errored, State::Finished)), +                    }, +                    State::Finished => { +                        // We do not let the stream die, as it would start a +                        // new download repeatedly if the user is not careful +                        // in case of errors. +                        let _: () = iced::futures::future::pending().await; + +                        None +                    } +                } +            }, +        )) +    } +} + +#[derive(Debug, Clone)] +pub enum Progress { +    Started, +    Advanced(f32), +    Finished, +    Errored, +} + +pub enum State { +    Ready(String), +    Downloading { +        response: reqwest::Response, +        total: u64, +        downloaded: u64, +    }, +    Finished, +} diff --git a/examples/download_progress/src/main.rs b/examples/download_progress/src/main.rs new file mode 100644 index 00000000..6c3094f7 --- /dev/null +++ b/examples/download_progress/src/main.rs @@ -0,0 +1,143 @@ +use iced::{ +    button, executor, Align, Application, Button, Column, Command, Container, +    Element, Length, ProgressBar, Settings, Subscription, Text, +}; + +mod download; + +pub fn main() { +    Example::run(Settings::default()) +} + +#[derive(Debug)] +enum Example { +    Idle { button: button::State }, +    Downloading { progress: f32 }, +    Finished { button: button::State }, +    Errored { button: button::State }, +} + +#[derive(Debug, Clone)] +pub enum Message { +    Download, +    DownloadProgressed(download::Progress), +} + +impl Application for Example { +    type Executor = executor::Default; +    type Message = Message; + +    fn new() -> (Example, Command<Message>) { +        ( +            Example::Idle { +                button: button::State::new(), +            }, +            Command::none(), +        ) +    } + +    fn title(&self) -> String { +        String::from("Download progress - Iced") +    } + +    fn update(&mut self, message: Message) -> Command<Message> { +        match message { +            Message::Download => match self { +                Example::Idle { .. } +                | Example::Finished { .. } +                | Example::Errored { .. } => { +                    *self = Example::Downloading { progress: 0.0 }; +                } +                _ => {} +            }, +            Message::DownloadProgressed(message) => match self { +                Example::Downloading { progress } => match message { +                    download::Progress::Started => { +                        *progress = 0.0; +                    } +                    download::Progress::Advanced(percentage) => { +                        *progress = percentage; +                    } +                    download::Progress::Finished => { +                        *self = Example::Finished { +                            button: button::State::new(), +                        } +                    } +                    download::Progress::Errored => { +                        *self = Example::Errored { +                            button: button::State::new(), +                        }; +                    } +                }, +                _ => {} +            }, +        }; + +        Command::none() +    } + +    fn subscription(&self) -> Subscription<Message> { +        match self { +            Example::Downloading { .. } => { +                download::file("https://speed.hetzner.de/100MB.bin") +                    .map(Message::DownloadProgressed) +            } +            _ => Subscription::none(), +        } +    } + +    fn view(&mut self) -> Element<Message> { +        let current_progress = match self { +            Example::Idle { .. } => 0.0, +            Example::Downloading { progress } => *progress, +            Example::Finished { .. } => 100.0, +            Example::Errored { .. } => 0.0, +        }; + +        let progress_bar = ProgressBar::new(0.0..=100.0, current_progress); + +        let control: Element<_> = match self { +            Example::Idle { button } => { +                Button::new(button, Text::new("Start the download!")) +                    .on_press(Message::Download) +                    .into() +            } +            Example::Finished { button } => Column::new() +                .spacing(10) +                .align_items(Align::Center) +                .push(Text::new("Download finished!")) +                .push( +                    Button::new(button, Text::new("Start again")) +                        .on_press(Message::Download), +                ) +                .into(), +            Example::Downloading { .. } => { +                Text::new(format!("Downloading... {:.2}%", current_progress)) +                    .into() +            } +            Example::Errored { button } => Column::new() +                .spacing(10) +                .align_items(Align::Center) +                .push(Text::new("Something went wrong :(")) +                .push( +                    Button::new(button, Text::new("Try again")) +                        .on_press(Message::Download), +                ) +                .into(), +        }; + +        let content = Column::new() +            .spacing(10) +            .padding(10) +            .align_items(Align::Center) +            .push(progress_bar) +            .push(control); + +        Container::new(content) +            .width(Length::Fill) +            .height(Length::Fill) +            .center_x() +            .center_y() +            .into() +    } +} diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 795c6a71..13a687ab 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -87,7 +87,7 @@ mod rainbow {              (                  Primitive::Mesh2D {                      origin: Point::new(b.x, b.y), -                    buffers: std::sync::Arc::new(Mesh2D { +                    buffers: Mesh2D {                          vertices: vec![                              Vertex2D {                                  position: posn_center, @@ -136,7 +136,7 @@ mod rainbow {                              0, 7, 8, // BL                              0, 8, 1, // L                          ], -                    }), +                    },                  },                  MouseCursor::OutOfBounds,              ) diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index ed36f736..2cb89ffc 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -10,7 +10,7 @@ use iced_wgpu::{  use iced_winit::{winit, Cache, Clipboard, MouseCursor, Size, UserInterface};  use winit::{ -    event::{DeviceEvent, Event, ModifiersState, WindowEvent}, +    event::{Event, ModifiersState, WindowEvent},      event_loop::{ControlFlow, EventLoop},  }; @@ -40,11 +40,12 @@ pub fn main() {          });      let surface = wgpu::Surface::create(&window); +    let format = wgpu::TextureFormat::Bgra8UnormSrgb;      let mut swap_chain = {          let size = window.inner_size(); -        SwapChain::new(&device, &surface, size.width, size.height) +        SwapChain::new(&device, &surface, format, size.width, size.height)      };      let mut resized = false; @@ -65,14 +66,11 @@ pub fn main() {          *control_flow = ControlFlow::Wait;          match event { -            Event::DeviceEvent { -                event: DeviceEvent::ModifiersChanged(new_modifiers), -                .. -            } => { -                modifiers = new_modifiers; -            }              Event::WindowEvent { event, .. } => {                  match event { +                    WindowEvent::ModifiersChanged(new_modifiers) => { +                        modifiers = new_modifiers; +                    }                      WindowEvent::Resized(new_size) => {                          logical_size =                              new_size.to_logical(window.scale_factor()); @@ -81,6 +79,7 @@ pub fn main() {                      WindowEvent::CloseRequested => {                          *control_flow = ControlFlow::Exit;                      } +                      _ => {}                  } @@ -163,6 +162,7 @@ pub fn main() {                      swap_chain = SwapChain::new(                          &device,                          &surface, +                        format,                          size.width,                          size.height,                      ); diff --git a/examples/pane_grid/Cargo.toml b/examples/pane_grid/Cargo.toml new file mode 100644 index 00000000..3ed912ac --- /dev/null +++ b/examples/pane_grid/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pane_grid" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] +edition = "2018" +publish = false + +[dependencies] +iced = { path = "../.." } diff --git a/examples/pane_grid/README.md b/examples/pane_grid/README.md new file mode 100644 index 00000000..3653fc5b --- /dev/null +++ b/examples/pane_grid/README.md @@ -0,0 +1,28 @@ +## Pane grid + +A grid of panes that can be split, resized, and reorganized. + +This example showcases the `PaneGrid` widget, which features: + +* Vertical and horizontal splits +* Tracking of the last active pane +* Mouse-based resizing +* Drag and drop to reorganize panes +* Hotkey support +* Configurable modifier keys +* API to perform actions programmatically (`split`, `swap`, `resize`, etc.) + +The __[`main`]__ file contains all the code of the example. + +<div align="center"> +  <a href="https://gfycat.com/mixedflatjellyfish"> +    <img src="https://thumbs.gfycat.com/MixedFlatJellyfish-small.gif"> +  </a> +</div> + +You can run it with `cargo run`: +``` +cargo run --package pane_grid +``` + +[`main`]: src/main.rs diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs new file mode 100644 index 00000000..dafc396c --- /dev/null +++ b/examples/pane_grid/src/main.rs @@ -0,0 +1,306 @@ +use iced::{ +    button, keyboard, pane_grid, scrollable, Align, Button, Column, Container, +    Element, HorizontalAlignment, Length, PaneGrid, Sandbox, Scrollable, +    Settings, Text, +}; + +pub fn main() { +    Example::run(Settings::default()) +} + +struct Example { +    panes: pane_grid::State<Content>, +    panes_created: usize, +} + +#[derive(Debug, Clone, Copy)] +enum Message { +    Split(pane_grid::Axis, pane_grid::Pane), +    SplitFocused(pane_grid::Axis), +    FocusAdjacent(pane_grid::Direction), +    Dragged(pane_grid::DragEvent), +    Resized(pane_grid::ResizeEvent), +    Close(pane_grid::Pane), +    CloseFocused, +} + +impl Sandbox for Example { +    type Message = Message; + +    fn new() -> Self { +        let (panes, _) = pane_grid::State::new(Content::new(0)); + +        Example { +            panes, +            panes_created: 1, +        } +    } + +    fn title(&self) -> String { +        String::from("Pane grid - Iced") +    } + +    fn update(&mut self, message: Message) { +        match message { +            Message::Split(axis, pane) => { +                let _ = self.panes.split( +                    axis, +                    &pane, +                    Content::new(self.panes_created), +                ); + +                self.panes_created += 1; +            } +            Message::SplitFocused(axis) => { +                if let Some(pane) = self.panes.active() { +                    let _ = self.panes.split( +                        axis, +                        &pane, +                        Content::new(self.panes_created), +                    ); + +                    self.panes_created += 1; +                } +            } +            Message::FocusAdjacent(direction) => { +                if let Some(pane) = self.panes.active() { +                    if let Some(adjacent) = +                        self.panes.adjacent(&pane, direction) +                    { +                        self.panes.focus(&adjacent); +                    } +                } +            } +            Message::Resized(pane_grid::ResizeEvent { split, ratio }) => { +                self.panes.resize(&split, ratio); +            } +            Message::Dragged(pane_grid::DragEvent::Dropped { +                pane, +                target, +            }) => { +                self.panes.swap(&pane, &target); +            } +            Message::Dragged(_) => {} +            Message::Close(pane) => { +                let _ = self.panes.close(&pane); +            } +            Message::CloseFocused => { +                if let Some(pane) = self.panes.active() { +                    let _ = self.panes.close(&pane); +                } +            } +        } +    } + +    fn view(&mut self) -> Element<Message> { +        let total_panes = self.panes.len(); + +        let pane_grid = +            PaneGrid::new(&mut self.panes, |pane, content, focus| { +                content.view(pane, focus, total_panes) +            }) +            .width(Length::Fill) +            .height(Length::Fill) +            .spacing(10) +            .on_drag(Message::Dragged) +            .on_resize(Message::Resized) +            .on_key_press(handle_hotkey); + +        Column::new() +            .width(Length::Fill) +            .height(Length::Fill) +            .padding(10) +            .push(pane_grid) +            .into() +    } +} + +fn handle_hotkey(event: pane_grid::KeyPressEvent) -> Option<Message> { +    use keyboard::KeyCode; +    use pane_grid::{Axis, Direction}; + +    let direction = match event.key_code { +        KeyCode::Up => Some(Direction::Up), +        KeyCode::Down => Some(Direction::Down), +        KeyCode::Left => Some(Direction::Left), +        KeyCode::Right => Some(Direction::Right), +        _ => None, +    }; + +    match event.key_code { +        KeyCode::V => Some(Message::SplitFocused(Axis::Vertical)), +        KeyCode::H => Some(Message::SplitFocused(Axis::Horizontal)), +        KeyCode::W => Some(Message::CloseFocused), +        _ => direction.map(Message::FocusAdjacent), +    } +} + +struct Content { +    id: usize, +    scroll: scrollable::State, +    split_horizontally: button::State, +    split_vertically: button::State, +    close: button::State, +} + +impl Content { +    fn new(id: usize) -> Self { +        Content { +            id, +            scroll: scrollable::State::new(), +            split_horizontally: button::State::new(), +            split_vertically: button::State::new(), +            close: button::State::new(), +        } +    } +    fn view( +        &mut self, +        pane: pane_grid::Pane, +        focus: Option<pane_grid::Focus>, +        total_panes: usize, +    ) -> Element<Message> { +        let Content { +            id, +            scroll, +            split_horizontally, +            split_vertically, +            close, +        } = self; + +        let button = |state, label, message, style| { +            Button::new( +                state, +                Text::new(label) +                    .width(Length::Fill) +                    .horizontal_alignment(HorizontalAlignment::Center) +                    .size(16), +            ) +            .width(Length::Fill) +            .padding(8) +            .on_press(message) +            .style(style) +        }; + +        let mut controls = Column::new() +            .spacing(5) +            .max_width(150) +            .push(button( +                split_horizontally, +                "Split horizontally", +                Message::Split(pane_grid::Axis::Horizontal, pane), +                style::Button::Primary, +            )) +            .push(button( +                split_vertically, +                "Split vertically", +                Message::Split(pane_grid::Axis::Vertical, pane), +                style::Button::Primary, +            )); + +        if total_panes > 1 { +            controls = controls.push(button( +                close, +                "Close", +                Message::Close(pane), +                style::Button::Destructive, +            )); +        } + +        let content = Scrollable::new(scroll) +            .width(Length::Fill) +            .spacing(10) +            .align_items(Align::Center) +            .push(Text::new(format!("Pane {}", id)).size(30)) +            .push(controls); + +        Container::new(Column::new().padding(5).push(content)) +            .width(Length::Fill) +            .height(Length::Fill) +            .center_y() +            .style(style::Pane { +                is_focused: focus.is_some(), +            }) +            .into() +    } +} + +mod style { +    use iced::{button, container, Background, Color, Vector}; + +    const SURFACE: Color = Color::from_rgb( +        0xF2 as f32 / 255.0, +        0xF3 as f32 / 255.0, +        0xF5 as f32 / 255.0, +    ); + +    const ACTIVE: Color = Color::from_rgb( +        0x72 as f32 / 255.0, +        0x89 as f32 / 255.0, +        0xDA as f32 / 255.0, +    ); + +    const HOVERED: Color = Color::from_rgb( +        0x67 as f32 / 255.0, +        0x7B as f32 / 255.0, +        0xC4 as f32 / 255.0, +    ); + +    pub struct Pane { +        pub is_focused: bool, +    } + +    impl container::StyleSheet for Pane { +        fn style(&self) -> container::Style { +            container::Style { +                background: Some(Background::Color(SURFACE)), +                border_width: 2, +                border_color: Color { +                    a: if self.is_focused { 1.0 } else { 0.3 }, +                    ..Color::BLACK +                }, +                ..Default::default() +            } +        } +    } + +    pub enum Button { +        Primary, +        Destructive, +    } + +    impl button::StyleSheet for Button { +        fn active(&self) -> button::Style { +            let (background, text_color) = match self { +                Button::Primary => (Some(ACTIVE), Color::WHITE), +                Button::Destructive => { +                    (None, Color::from_rgb8(0xFF, 0x47, 0x47)) +                } +            }; + +            button::Style { +                text_color, +                background: background.map(Background::Color), +                border_radius: 5, +                shadow_offset: Vector::new(0.0, 0.0), +                ..button::Style::default() +            } +        } + +        fn hovered(&self) -> button::Style { +            let active = self.active(); + +            let background = match self { +                Button::Primary => Some(HOVERED), +                Button::Destructive => Some(Color { +                    a: 0.2, +                    ..active.text_color +                }), +            }; + +            button::Style { +                background: background.map(Background::Color), +                ..active +            } +        } +    } +} diff --git a/examples/pokedex/Cargo.toml b/examples/pokedex/Cargo.toml index c1e3edb5..94320086 100644 --- a/examples/pokedex/Cargo.toml +++ b/examples/pokedex/Cargo.toml @@ -7,12 +7,16 @@ publish = false  [dependencies]  iced = { path = "../..", features = ["image", "debug", "tokio"] } -serde = { version = "1.0", features = ["derive"] }  serde_json = "1.0" -rand = { version = "0.7", features = ["wasm-bindgen"] } + +[dependencies.serde] +version = "1.0" +features = ["derive"]  [dependencies.reqwest] -version = "0.10" -git = "https://github.com/hecrj/reqwest.git" -branch = "feature/wasm-deserialize-json" +version = "0.10.2"  features = ["json"] + +[dependencies.rand] +version = "0.7" +features = ["wasm-bindgen"] diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index e97389e9..dfa168b6 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -93,6 +93,7 @@ impl Sandbox for Styling {              ProgressBar::new(0.0..=100.0, self.slider_value).style(self.theme);          let scrollable = Scrollable::new(&mut self.scroll) +            .width(Length::Fill)              .height(Length::Units(100))              .style(self.theme)              .push(Text::new("Scroll me!")) diff --git a/examples/svg/Cargo.toml b/examples/svg/Cargo.toml index d8f83ac2..161ee6a8 100644 --- a/examples/svg/Cargo.toml +++ b/examples/svg/Cargo.toml @@ -7,3 +7,4 @@ publish = false  [dependencies]  iced = { path = "../..", features = ["svg"] } +env_logger = "0.7" diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index 1fb80534..811fdfb5 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -1,6 +1,8 @@  use iced::{Column, Container, Element, Length, Sandbox, Settings, Svg};  pub fn main() { +    env_logger::init(); +      Tiger::run(Settings::default())  } @@ -22,9 +24,12 @@ impl Sandbox for Tiger {      fn view(&mut self) -> Element<()> {          let content = Column::new().padding(20).push( -            Svg::new(format!("{}/resources/tiger.svg", env!("CARGO_MANIFEST_DIR"))) -                .width(Length::Fill) -                .height(Length::Fill), +            Svg::new(format!( +                "{}/resources/tiger.svg", +                env!("CARGO_MANIFEST_DIR") +            )) +            .width(Length::Fill) +            .height(Length::Fill),          );          Container::new(content)  | 
