From c901f40fd6c5aa39f4dc056b2b59bc7133b287e6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 14 Apr 2020 12:11:10 +0200 Subject: Introduce `Widget::overlay` :tada: --- examples/custom_widget/src/main.rs | 2 +- examples/geometry/src/main.rs | 2 +- examples/todos/src/main.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index bcf896b0..a6068f91 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -25,7 +25,7 @@ mod circle { } } - impl Widget> for Circle + impl<'a, Message, B> Widget<'a, Message, Renderer> for Circle where B: Backend, { diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 71ce0d8c..3795323a 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -27,7 +27,7 @@ mod rainbow { } } - impl Widget> for Rainbow + impl<'a, Message, B> Widget<'a, Message, Renderer> for Rainbow where B: Backend, { diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index c9cbcc69..5713a6f2 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -425,7 +425,7 @@ impl Filter { } } -fn loading_message() -> Element<'static, Message> { +fn loading_message<'a>() -> Element<'a, Message> { Container::new( Text::new("Loading...") .horizontal_alignment(HorizontalAlignment::Center) @@ -437,7 +437,7 @@ fn loading_message() -> Element<'static, Message> { .into() } -fn empty_message(message: &str) -> Element<'static, Message> { +fn empty_message<'a>(message: &str) -> Element<'a, Message> { Container::new( Text::new(message) .width(Length::Fill) -- cgit From b1afadf1a2162e236525c466b6b3099a2623a2de Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 16 Apr 2020 13:22:55 +0200 Subject: Draft `combo_box` example to test overlay logic --- examples/combo_box/Cargo.toml | 11 +++ examples/combo_box/README.md | 18 +++++ examples/combo_box/src/main.rs | 163 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 examples/combo_box/Cargo.toml create mode 100644 examples/combo_box/README.md create mode 100644 examples/combo_box/src/main.rs (limited to 'examples') diff --git a/examples/combo_box/Cargo.toml b/examples/combo_box/Cargo.toml new file mode 100644 index 00000000..7e1e4133 --- /dev/null +++ b/examples/combo_box/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "combo_box" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez "] +edition = "2018" +publish = false + +[dependencies] +iced = { path = "../..", features = ["debug"] } +iced_native = { path = "../../native" } +iced_wgpu = { path = "../../wgpu" } diff --git a/examples/combo_box/README.md b/examples/combo_box/README.md new file mode 100644 index 00000000..4d9fc5b9 --- /dev/null +++ b/examples/combo_box/README.md @@ -0,0 +1,18 @@ +## Counter + +The classic counter example explained in the [`README`](../../README.md). + +The __[`main`]__ file contains all the code of the example. + + + +You can run it with `cargo run`: +``` +cargo run --package counter +``` + +[`main`]: src/main.rs diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs new file mode 100644 index 00000000..742378c0 --- /dev/null +++ b/examples/combo_box/src/main.rs @@ -0,0 +1,163 @@ +mod combo_box { + use iced_native::{ + layout, mouse, Background, Color, Element, Hasher, Layer, Layout, + Length, Overlay, Point, Size, Vector, Widget, + }; + use iced_wgpu::{Defaults, Primitive, Renderer}; + + pub struct ComboBox; + + impl ComboBox { + pub fn new() -> Self { + Self + } + } + + impl<'a, Message> Widget<'a, Message, Renderer> for ComboBox { + fn width(&self) -> Length { + Length::Shrink + } + + fn height(&self) -> Length { + Length::Shrink + } + + fn layout( + &self, + _renderer: &Renderer, + _limits: &layout::Limits, + ) -> layout::Node { + layout::Node::new(Size::new(50.0, 50.0)) + } + + fn hash_layout(&self, _state: &mut Hasher) {} + + fn draw( + &self, + _renderer: &mut Renderer, + _defaults: &Defaults, + layout: Layout<'_>, + _cursor_position: Point, + ) -> (Primitive, mouse::Interaction) { + let primitive = Primitive::Quad { + bounds: layout.bounds(), + background: Background::Color(Color::BLACK), + border_width: 0, + border_radius: 0, + border_color: Color::TRANSPARENT, + }; + + (primitive, mouse::Interaction::default()) + } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + Some(Overlay::new(layout.position(), Box::new(Menu))) + } + } + + impl<'a, Message> Into> for ComboBox { + fn into(self) -> Element<'a, Message, Renderer> { + Element::new(self) + } + } + + pub struct Menu; + + impl Layer for Menu { + fn layout( + &self, + _renderer: &Renderer, + _bounds: Size, + position: Point, + ) -> layout::Node { + let mut node = layout::Node::new(Size::new(100.0, 100.0)); + + node.move_to(position + Vector::new(25.0, 25.0)); + + node + } + + fn hash_layout(&self, state: &mut Hasher, position: Point) { + use std::hash::Hash; + + (position.x as u32).hash(state); + (position.y as u32).hash(state); + } + + fn draw( + &self, + _renderer: &mut Renderer, + _defaults: &Defaults, + layout: Layout<'_>, + _cursor_position: Point, + ) -> (Primitive, mouse::Interaction) { + let primitive = Primitive::Quad { + bounds: layout.bounds(), + background: Background::Color(Color { + r: 0.0, + g: 0.0, + b: 1.0, + a: 0.5, + }), + border_width: 0, + border_radius: 0, + border_color: Color::TRANSPARENT, + }; + + (primitive, mouse::Interaction::default()) + } + } +} + +pub use combo_box::ComboBox; + +use iced::{ + button, Button, Column, Container, Element, Length, Sandbox, Settings, Text, +}; + +pub fn main() { + Example::run(Settings::default()) +} + +#[derive(Default)] +struct Example { + button: button::State, +} + +#[derive(Debug, Clone, Copy)] +enum Message { + ButtonPressed, +} + +impl Sandbox for Example { + type Message = Message; + + fn new() -> Self { + Self::default() + } + + fn title(&self) -> String { + String::from("Combo box - Iced") + } + + fn update(&mut self, _message: Message) {} + + fn view(&mut self) -> Element { + let combo_box = ComboBox::new(); + + let button = Button::new(&mut self.button, Text::new("Press me!")) + .on_press(Message::ButtonPressed); + + let content = Column::new().spacing(10).push(combo_box).push(button); + + Container::new(content) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y() + .into() + } +} -- cgit From afd9274de26ccf65285df02007b4ddb697bea9a3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 18 Apr 2020 14:42:48 +0200 Subject: Draft `ComboBox` and `Menu` layer --- examples/combo_box/src/main.rs | 196 ++++++++++++++++------------------------- 1 file changed, 76 insertions(+), 120 deletions(-) (limited to 'examples') diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs index 742378c0..75a3f713 100644 --- a/examples/combo_box/src/main.rs +++ b/examples/combo_box/src/main.rs @@ -1,121 +1,6 @@ -mod combo_box { - use iced_native::{ - layout, mouse, Background, Color, Element, Hasher, Layer, Layout, - Length, Overlay, Point, Size, Vector, Widget, - }; - use iced_wgpu::{Defaults, Primitive, Renderer}; - - pub struct ComboBox; - - impl ComboBox { - pub fn new() -> Self { - Self - } - } - - impl<'a, Message> Widget<'a, Message, Renderer> for ComboBox { - fn width(&self) -> Length { - Length::Shrink - } - - fn height(&self) -> Length { - Length::Shrink - } - - fn layout( - &self, - _renderer: &Renderer, - _limits: &layout::Limits, - ) -> layout::Node { - layout::Node::new(Size::new(50.0, 50.0)) - } - - fn hash_layout(&self, _state: &mut Hasher) {} - - fn draw( - &self, - _renderer: &mut Renderer, - _defaults: &Defaults, - layout: Layout<'_>, - _cursor_position: Point, - ) -> (Primitive, mouse::Interaction) { - let primitive = Primitive::Quad { - bounds: layout.bounds(), - background: Background::Color(Color::BLACK), - border_width: 0, - border_radius: 0, - border_color: Color::TRANSPARENT, - }; - - (primitive, mouse::Interaction::default()) - } - - fn overlay( - &mut self, - layout: Layout<'_>, - ) -> Option> { - Some(Overlay::new(layout.position(), Box::new(Menu))) - } - } - - impl<'a, Message> Into> for ComboBox { - fn into(self) -> Element<'a, Message, Renderer> { - Element::new(self) - } - } - - pub struct Menu; - - impl Layer for Menu { - fn layout( - &self, - _renderer: &Renderer, - _bounds: Size, - position: Point, - ) -> layout::Node { - let mut node = layout::Node::new(Size::new(100.0, 100.0)); - - node.move_to(position + Vector::new(25.0, 25.0)); - - node - } - - fn hash_layout(&self, state: &mut Hasher, position: Point) { - use std::hash::Hash; - - (position.x as u32).hash(state); - (position.y as u32).hash(state); - } - - fn draw( - &self, - _renderer: &mut Renderer, - _defaults: &Defaults, - layout: Layout<'_>, - _cursor_position: Point, - ) -> (Primitive, mouse::Interaction) { - let primitive = Primitive::Quad { - bounds: layout.bounds(), - background: Background::Color(Color { - r: 0.0, - g: 0.0, - b: 1.0, - a: 0.5, - }), - border_width: 0, - border_radius: 0, - border_color: Color::TRANSPARENT, - }; - - (primitive, mouse::Interaction::default()) - } - } -} - -pub use combo_box::ComboBox; - use iced::{ - button, Button, Column, Container, Element, Length, Sandbox, Settings, Text, + button, combo_box, Button, Column, ComboBox, Container, Element, Length, + Sandbox, Settings, Text, }; pub fn main() { @@ -125,11 +10,14 @@ pub fn main() { #[derive(Default)] struct Example { button: button::State, + combo_box: combo_box::State, + selected_language: Language, } #[derive(Debug, Clone, Copy)] enum Message { ButtonPressed, + LanguageSelected(Language), } impl Sandbox for Example { @@ -143,15 +31,36 @@ impl Sandbox for Example { String::from("Combo box - Iced") } - fn update(&mut self, _message: Message) {} + fn update(&mut self, message: Message) { + match message { + Message::ButtonPressed => {} + Message::LanguageSelected(language) => { + self.selected_language = language; + } + } + } fn view(&mut self) -> Element { - let combo_box = ComboBox::new(); + let combo_box = ComboBox::new( + &mut self.combo_box, + &Language::ALL[..], + Some(self.selected_language), + Message::LanguageSelected, + ); let button = Button::new(&mut self.button, Text::new("Press me!")) .on_press(Message::ButtonPressed); - let content = Column::new().spacing(10).push(combo_box).push(button); + let mut content = Column::new() + .spacing(10) + .push(Text::new("Which is your favorite language?")) + .push(combo_box); + + if self.selected_language == Language::Javascript { + content = content.push(Text::new("You are wrong!")); + } + + content = content.push(button); Container::new(content) .width(Length::Fill) @@ -161,3 +70,50 @@ impl Sandbox for Example { .into() } } + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Language { + Rust, + Elm, + Ruby, + Haskell, + C, + Javascript, + Other, +} + +impl Language { + const ALL: [Language; 7] = [ + Language::C, + Language::Elm, + Language::Ruby, + Language::Haskell, + Language::Rust, + Language::Javascript, + Language::Other, + ]; +} + +impl Default for Language { + fn default() -> Language { + Language::Rust + } +} + +impl std::fmt::Display for Language { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Language::Rust => "Rust", + Language::Elm => "Elm", + Language::Ruby => "Ruby", + Language::Haskell => "Haskell", + Language::C => "C", + Language::Javascript => "Javascript", + Language::Other => "Some other language", + } + ) + } +} -- cgit From ada8d7c77f9e1d4a1de762b514c9610f7e09b17f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 18 Apr 2020 19:28:05 +0200 Subject: Implement `Widget::overlay` for `Scrollable` --- examples/combo_box/src/main.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs index 75a3f713..977dc196 100644 --- a/examples/combo_box/src/main.rs +++ b/examples/combo_box/src/main.rs @@ -1,6 +1,6 @@ use iced::{ - button, combo_box, Button, Column, ComboBox, Container, Element, Length, - Sandbox, Settings, Text, + button, combo_box, scrollable, Align, Button, ComboBox, Container, Element, + Length, Sandbox, Scrollable, Settings, Space, Text, }; pub fn main() { @@ -9,6 +9,7 @@ pub fn main() { #[derive(Default)] struct Example { + scroll: scrollable::State, button: button::State, combo_box: combo_box::State, selected_language: Language, @@ -51,8 +52,11 @@ impl Sandbox for Example { let button = Button::new(&mut self.button, Text::new("Press me!")) .on_press(Message::ButtonPressed); - let mut content = Column::new() + let mut content = Scrollable::new(&mut self.scroll) + .width(Length::Fill) + .align_items(Align::Center) .spacing(10) + .push(Space::with_height(Length::Units(800))) .push(Text::new("Which is your favorite language?")) .push(combo_box); @@ -60,7 +64,9 @@ impl Sandbox for Example { content = content.push(Text::new("You are wrong!")); } - content = content.push(button); + content = content + .push(button) + .push(Space::with_height(Length::Units(800))); Container::new(content) .width(Length::Fill) -- cgit From f655d9b9674fe5a705e26b8797231d93a117395b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 18 Apr 2020 20:44:14 +0200 Subject: Position `Menu` layer based on available space --- examples/combo_box/src/main.rs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'examples') diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs index 977dc196..416e9f76 100644 --- a/examples/combo_box/src/main.rs +++ b/examples/combo_box/src/main.rs @@ -60,10 +60,6 @@ impl Sandbox for Example { .push(Text::new("Which is your favorite language?")) .push(combo_box); - if self.selected_language == Language::Javascript { - content = content.push(Text::new("You are wrong!")); - } - content = content .push(button) .push(Space::with_height(Length::Units(800))); -- cgit From dc0e423142f053c59c326d92920e7829b6852cca Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 02:01:30 +0200 Subject: Remove unnecessary lifetime in `Widget` trait --- examples/custom_widget/src/main.rs | 2 +- examples/geometry/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index a6068f91..bcf896b0 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -25,7 +25,7 @@ mod circle { } } - impl<'a, Message, B> Widget<'a, Message, Renderer> for Circle + impl Widget> for Circle where B: Backend, { diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 3795323a..71ce0d8c 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -27,7 +27,7 @@ mod rainbow { } } - impl<'a, Message, B> Widget<'a, Message, Renderer> for Rainbow + impl Widget> for Rainbow where B: Backend, { -- cgit From 73b8ae8e5e7f57c608c775272a2980995ab22bb3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 02:50:47 +0200 Subject: Rename `ComboBox` to `PickList` --- examples/combo_box/Cargo.toml | 11 ---- examples/combo_box/README.md | 18 ------ examples/combo_box/src/main.rs | 121 ----------------------------------------- examples/pick_list/Cargo.toml | 9 +++ examples/pick_list/README.md | 18 ++++++ examples/pick_list/src/main.rs | 121 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 148 insertions(+), 150 deletions(-) delete mode 100644 examples/combo_box/Cargo.toml delete mode 100644 examples/combo_box/README.md delete mode 100644 examples/combo_box/src/main.rs create mode 100644 examples/pick_list/Cargo.toml create mode 100644 examples/pick_list/README.md create mode 100644 examples/pick_list/src/main.rs (limited to 'examples') diff --git a/examples/combo_box/Cargo.toml b/examples/combo_box/Cargo.toml deleted file mode 100644 index 7e1e4133..00000000 --- a/examples/combo_box/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "combo_box" -version = "0.1.0" -authors = ["Héctor Ramón Jiménez "] -edition = "2018" -publish = false - -[dependencies] -iced = { path = "../..", features = ["debug"] } -iced_native = { path = "../../native" } -iced_wgpu = { path = "../../wgpu" } diff --git a/examples/combo_box/README.md b/examples/combo_box/README.md deleted file mode 100644 index 4d9fc5b9..00000000 --- a/examples/combo_box/README.md +++ /dev/null @@ -1,18 +0,0 @@ -## Counter - -The classic counter example explained in the [`README`](../../README.md). - -The __[`main`]__ file contains all the code of the example. - - - -You can run it with `cargo run`: -``` -cargo run --package counter -``` - -[`main`]: src/main.rs diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs deleted file mode 100644 index 416e9f76..00000000 --- a/examples/combo_box/src/main.rs +++ /dev/null @@ -1,121 +0,0 @@ -use iced::{ - button, combo_box, scrollable, Align, Button, ComboBox, Container, Element, - Length, Sandbox, Scrollable, Settings, Space, Text, -}; - -pub fn main() { - Example::run(Settings::default()) -} - -#[derive(Default)] -struct Example { - scroll: scrollable::State, - button: button::State, - combo_box: combo_box::State, - selected_language: Language, -} - -#[derive(Debug, Clone, Copy)] -enum Message { - ButtonPressed, - LanguageSelected(Language), -} - -impl Sandbox for Example { - type Message = Message; - - fn new() -> Self { - Self::default() - } - - fn title(&self) -> String { - String::from("Combo box - Iced") - } - - fn update(&mut self, message: Message) { - match message { - Message::ButtonPressed => {} - Message::LanguageSelected(language) => { - self.selected_language = language; - } - } - } - - fn view(&mut self) -> Element { - let combo_box = ComboBox::new( - &mut self.combo_box, - &Language::ALL[..], - Some(self.selected_language), - Message::LanguageSelected, - ); - - let button = Button::new(&mut self.button, Text::new("Press me!")) - .on_press(Message::ButtonPressed); - - let mut content = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .align_items(Align::Center) - .spacing(10) - .push(Space::with_height(Length::Units(800))) - .push(Text::new("Which is your favorite language?")) - .push(combo_box); - - content = content - .push(button) - .push(Space::with_height(Length::Units(800))); - - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Language { - Rust, - Elm, - Ruby, - Haskell, - C, - Javascript, - Other, -} - -impl Language { - const ALL: [Language; 7] = [ - Language::C, - Language::Elm, - Language::Ruby, - Language::Haskell, - Language::Rust, - Language::Javascript, - Language::Other, - ]; -} - -impl Default for Language { - fn default() -> Language { - Language::Rust - } -} - -impl std::fmt::Display for Language { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - Language::Rust => "Rust", - Language::Elm => "Elm", - Language::Ruby => "Ruby", - Language::Haskell => "Haskell", - Language::C => "C", - Language::Javascript => "Javascript", - Language::Other => "Some other language", - } - ) - } -} diff --git a/examples/pick_list/Cargo.toml b/examples/pick_list/Cargo.toml new file mode 100644 index 00000000..a87d7217 --- /dev/null +++ b/examples/pick_list/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pick_list" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez "] +edition = "2018" +publish = false + +[dependencies] +iced = { path = "../..", features = ["debug"] } diff --git a/examples/pick_list/README.md b/examples/pick_list/README.md new file mode 100644 index 00000000..4d9fc5b9 --- /dev/null +++ b/examples/pick_list/README.md @@ -0,0 +1,18 @@ +## Counter + +The classic counter example explained in the [`README`](../../README.md). + +The __[`main`]__ file contains all the code of the example. + + + +You can run it with `cargo run`: +``` +cargo run --package counter +``` + +[`main`]: src/main.rs diff --git a/examples/pick_list/src/main.rs b/examples/pick_list/src/main.rs new file mode 100644 index 00000000..4eb368d1 --- /dev/null +++ b/examples/pick_list/src/main.rs @@ -0,0 +1,121 @@ +use iced::{ + button, pick_list, scrollable, Align, Button, Container, Element, Length, + PickList, Sandbox, Scrollable, Settings, Space, Text, +}; + +pub fn main() { + Example::run(Settings::default()) +} + +#[derive(Default)] +struct Example { + scroll: scrollable::State, + button: button::State, + pick_list: pick_list::State, + selected_language: Language, +} + +#[derive(Debug, Clone, Copy)] +enum Message { + ButtonPressed, + LanguageSelected(Language), +} + +impl Sandbox for Example { + type Message = Message; + + fn new() -> Self { + Self::default() + } + + fn title(&self) -> String { + String::from("Pick list - Iced") + } + + fn update(&mut self, message: Message) { + match message { + Message::ButtonPressed => {} + Message::LanguageSelected(language) => { + self.selected_language = language; + } + } + } + + fn view(&mut self) -> Element { + let pick_list = PickList::new( + &mut self.pick_list, + &Language::ALL[..], + Some(self.selected_language), + Message::LanguageSelected, + ); + + let button = Button::new(&mut self.button, Text::new("Press me!")) + .on_press(Message::ButtonPressed); + + let mut content = Scrollable::new(&mut self.scroll) + .width(Length::Fill) + .align_items(Align::Center) + .spacing(10) + .push(Space::with_height(Length::Units(800))) + .push(Text::new("Which is your favorite language?")) + .push(pick_list); + + content = content + .push(button) + .push(Space::with_height(Length::Units(800))); + + Container::new(content) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y() + .into() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Language { + Rust, + Elm, + Ruby, + Haskell, + C, + Javascript, + Other, +} + +impl Language { + const ALL: [Language; 7] = [ + Language::C, + Language::Elm, + Language::Ruby, + Language::Haskell, + Language::Rust, + Language::Javascript, + Language::Other, + ]; +} + +impl Default for Language { + fn default() -> Language { + Language::Rust + } +} + +impl std::fmt::Display for Language { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Language::Rust => "Rust", + Language::Elm => "Elm", + Language::Ruby => "Ruby", + Language::Haskell => "Haskell", + Language::C => "C", + Language::Javascript => "Javascript", + Language::Other => "Some other language", + } + ) + } +} -- cgit From b64e0ea5e31e718e435b24244119f59f7128bc27 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 04:14:21 +0200 Subject: Add `Preset` selector to `game_of_life` example --- examples/game_of_life/src/main.rs | 79 +++++++++++++++++--- examples/game_of_life/src/preset.rs | 142 ++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 12 deletions(-) create mode 100644 examples/game_of_life/src/preset.rs (limited to 'examples') diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index 080d55c0..4663ae72 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -1,15 +1,19 @@ //! This example showcases an interactive version of the Game of Life, invented //! by John Conway. It leverages a `Canvas` together with other widgets. +mod preset; mod style; use grid::Grid; +use iced::button::{self, Button}; +use iced::executor; +use iced::pick_list::{self, PickList}; +use iced::slider::{self, Slider}; +use iced::time; use iced::{ - button::{self, Button}, - executor, - slider::{self, Slider}, - time, Align, Application, Checkbox, Column, Command, Container, Element, - Length, Row, Settings, Subscription, Text, + Align, Application, Checkbox, Column, Command, Container, Element, Length, + Row, Settings, Subscription, Text, }; +use preset::Preset; use std::time::{Duration, Instant}; pub fn main() { @@ -38,6 +42,7 @@ enum Message { Next, Clear, SpeedChanged(f32), + PresetPicked(Preset), } impl Application for GameOfLife { @@ -48,7 +53,7 @@ impl Application for GameOfLife { fn new(_flags: ()) -> (Self, Command) { ( Self { - speed: 1, + speed: 5, ..Self::default() }, Command::none(), @@ -93,6 +98,9 @@ impl Application for GameOfLife { self.speed = speed.round() as usize; } } + Message::PresetPicked(new_preset) => { + self.grid = Grid::from_preset(new_preset); + } } Command::none() @@ -113,6 +121,7 @@ impl Application for GameOfLife { self.is_playing, self.grid.are_lines_visible(), selected_speed, + self.grid.preset(), ); let content = Column::new() @@ -128,6 +137,7 @@ impl Application for GameOfLife { } mod grid { + use crate::Preset; use iced::{ canvas::{ self, Cache, Canvas, Cursor, Event, Frame, Geometry, Path, Text, @@ -142,6 +152,7 @@ mod grid { pub struct Grid { state: State, + preset: Preset, interaction: Interaction, life_cache: Cache, grid_cache: Cache, @@ -171,8 +182,24 @@ mod grid { impl Default for Grid { fn default() -> Self { + Self::from_preset(Preset::default()) + } + } + + impl Grid { + const MIN_SCALING: f32 = 0.1; + const MAX_SCALING: f32 = 2.0; + + pub fn from_preset(preset: Preset) -> Self { Self { - state: State::default(), + state: State::with_life( + preset + .life() + .into_iter() + .map(|(i, j)| Cell { i, j }) + .collect(), + ), + preset, interaction: Interaction::None, life_cache: Cache::default(), grid_cache: Cache::default(), @@ -184,11 +211,6 @@ mod grid { version: 0, } } - } - - impl Grid { - const MIN_SCALING: f32 = 0.1; - const MAX_SCALING: f32 = 2.0; pub fn tick( &mut self, @@ -217,10 +239,14 @@ mod grid { Message::Populate(cell) => { self.state.populate(cell); self.life_cache.clear(); + + self.preset = Preset::Custom; } Message::Unpopulate(cell) => { self.state.unpopulate(&cell); self.life_cache.clear(); + + self.preset = Preset::Custom; } Message::Ticked { result: Ok(life), @@ -230,6 +256,7 @@ mod grid { self.state.update(life); self.life_cache.clear(); + self.version += 1; self.last_tick_duration = tick_duration; } Message::Ticked { @@ -250,11 +277,16 @@ mod grid { pub fn clear(&mut self) { self.state = State::default(); + self.preset = Preset::Custom; self.version += 1; self.life_cache.clear(); } + pub fn preset(&self) -> Preset { + self.preset + } + pub fn toggle_lines(&mut self, enabled: bool) { self.show_lines = enabled; } @@ -533,6 +565,13 @@ mod grid { } impl State { + pub fn with_life(life: Life) -> Self { + Self { + life, + ..Self::default() + } + } + fn cell_count(&self) -> usize { self.life.len() + self.births.len() } @@ -647,6 +686,14 @@ mod grid { } } + impl std::iter::FromIterator for Life { + fn from_iter>(iter: I) -> Self { + Life { + cells: iter.into_iter().collect(), + } + } + } + impl std::fmt::Debug for Life { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Life") @@ -741,6 +788,7 @@ struct Controls { next_button: button::State, clear_button: button::State, speed_slider: slider::State, + preset_list: pick_list::State, } impl Controls { @@ -749,6 +797,7 @@ impl Controls { is_playing: bool, is_grid_enabled: bool, speed: usize, + preset: Preset, ) -> Element<'a, Message> { let playback_controls = Row::new() .spacing(10) @@ -793,6 +842,12 @@ impl Controls { .spacing(5) .text_size(16), ) + .push(PickList::new( + &mut self.preset_list, + preset::ALL, + Some(preset), + Message::PresetPicked, + )) .push( Button::new(&mut self.clear_button, Text::new("Clear")) .on_press(Message::Clear) diff --git a/examples/game_of_life/src/preset.rs b/examples/game_of_life/src/preset.rs new file mode 100644 index 00000000..1a471141 --- /dev/null +++ b/examples/game_of_life/src/preset.rs @@ -0,0 +1,142 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Preset { + Custom, + XKCD, + Glider, + SmallExploder, + Exploder, + TenCellRow, + LightweightSpaceship, + Tumbler, + Acorn, + GliderGun, +} + +pub static ALL: &[Preset] = &[ + Preset::Custom, + Preset::XKCD, + Preset::Glider, + Preset::SmallExploder, + Preset::Exploder, + Preset::TenCellRow, + Preset::LightweightSpaceship, + Preset::Tumbler, + Preset::Acorn, + Preset::GliderGun, +]; + +impl Preset { + pub fn life(self) -> Vec<(isize, isize)> { + #[rustfmt::skip] + let cells = match self { + Preset::Custom => vec![], + Preset::XKCD => vec![ + " xxx ", + " x x ", + " x x ", + " x ", + "x xxx ", + " x x x ", + " x x", + " x x ", + " x x ", + ], + Preset::Glider => vec![ + " x ", + " x", + "xxx" + ], + Preset::SmallExploder => vec![ + " x ", + "xxx", + "x x", + " x ", + ], + Preset::Exploder => vec![ + "x x x", + "x x", + "x x", + "x x", + "x x x", + ], + Preset::TenCellRow => vec![ + "xxxxxxxxxx", + ], + Preset::LightweightSpaceship => vec![ + " xxxxx", + "x x", + " x", + "x x ", + ], + Preset::Tumbler => vec![ + " xx xx ", + " xx xx ", + " x x ", + "x x x x", + "x x x x", + "xx xx", + ], + Preset::Acorn => vec![ + " x ", + " x ", + "xx xxx", + ], + Preset::GliderGun => vec![ + " x ", + " x x ", + " xx xx xx", + " x x xx xx", + "xx x x xx ", + "xx x x xx x x ", + " x x x ", + " x x ", + " xx ", + ] + }; + + let start_row = -(cells.len() as isize / 2); + + cells + .into_iter() + .enumerate() + .flat_map(|(i, cells)| { + let start_column = -(cells.len() as isize / 2); + + cells + .chars() + .enumerate() + .filter(|(_, c)| !c.is_whitespace()) + .map(move |(j, _)| { + (start_row + i as isize, start_column + j as isize) + }) + }) + .collect() + } +} + +impl Default for Preset { + fn default() -> Preset { + Preset::XKCD + } +} + +impl std::fmt::Display for Preset { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Preset::Custom => "Custom", + Preset::XKCD => "xkcd #2293", + Preset::Glider => "Glider", + Preset::SmallExploder => "Small Exploder", + Preset::Exploder => "Exploder", + Preset::TenCellRow => "10 Cell Row", + Preset::LightweightSpaceship => "Lightweight spaceship", + Preset::Tumbler => "Tumbler", + Preset::Acorn => "Acorn", + Preset::GliderGun => "Gosper Glider Gun", + } + ) + } +} -- cgit From 94383d82a5d080a28de025fadc6b7ba27e37927d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 07:41:31 +0200 Subject: Style `PickList` in `game_of_life` example --- examples/game_of_life/src/main.rs | 17 +++++++---- examples/game_of_life/src/preset.rs | 18 ++++++------ examples/game_of_life/src/style.rs | 56 ++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 16 deletions(-) (limited to 'examples') diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index 4663ae72..27d4eec1 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -842,12 +842,17 @@ impl Controls { .spacing(5) .text_size(16), ) - .push(PickList::new( - &mut self.preset_list, - preset::ALL, - Some(preset), - Message::PresetPicked, - )) + .push( + PickList::new( + &mut self.preset_list, + preset::ALL, + Some(preset), + Message::PresetPicked, + ) + .padding(8) + .text_size(16) + .style(style::PickList), + ) .push( Button::new(&mut self.clear_button, Text::new("Clear")) .on_press(Message::Clear) diff --git a/examples/game_of_life/src/preset.rs b/examples/game_of_life/src/preset.rs index 1a471141..05157b6a 100644 --- a/examples/game_of_life/src/preset.rs +++ b/examples/game_of_life/src/preset.rs @@ -8,8 +8,8 @@ pub enum Preset { TenCellRow, LightweightSpaceship, Tumbler, - Acorn, GliderGun, + Acorn, } pub static ALL: &[Preset] = &[ @@ -21,8 +21,8 @@ pub static ALL: &[Preset] = &[ Preset::TenCellRow, Preset::LightweightSpaceship, Preset::Tumbler, - Preset::Acorn, Preset::GliderGun, + Preset::Acorn, ]; impl Preset { @@ -76,11 +76,6 @@ impl Preset { "x x x x", "xx xx", ], - Preset::Acorn => vec![ - " x ", - " x ", - "xx xxx", - ], Preset::GliderGun => vec![ " x ", " x x ", @@ -91,7 +86,12 @@ impl Preset { " x x x ", " x x ", " xx ", - ] + ], + Preset::Acorn => vec![ + " x ", + " x ", + "xx xxx", + ], }; let start_row = -(cells.len() as isize / 2); @@ -134,8 +134,8 @@ impl std::fmt::Display for Preset { Preset::TenCellRow => "10 Cell Row", Preset::LightweightSpaceship => "Lightweight spaceship", Preset::Tumbler => "Tumbler", - Preset::Acorn => "Acorn", Preset::GliderGun => "Gosper Glider Gun", + Preset::Acorn => "Acorn", } ) } diff --git a/examples/game_of_life/src/style.rs b/examples/game_of_life/src/style.rs index d59569f2..308ce43c 100644 --- a/examples/game_of_life/src/style.rs +++ b/examples/game_of_life/src/style.rs @@ -1,4 +1,4 @@ -use iced::{button, container, slider, Background, Color}; +use iced::{button, container, pick_list, slider, Background, Color}; const ACTIVE: Color = Color::from_rgb( 0x72 as f32 / 255.0, @@ -18,6 +18,12 @@ const HOVERED: Color = Color::from_rgb( 0xC4 as f32 / 255.0, ); +const BACKGROUND: Color = Color::from_rgb( + 0x2F as f32 / 255.0, + 0x31 as f32 / 255.0, + 0x36 as f32 / 255.0, +); + pub struct Container; impl container::StyleSheet for Container { @@ -132,3 +138,51 @@ impl slider::StyleSheet for Slider { } } } + +pub struct PickList; + +impl pick_list::StyleSheet for PickList { + fn menu(&self) -> pick_list::Menu { + pick_list::Menu { + text_color: Color::WHITE, + background: BACKGROUND.into(), + border_width: 1, + border_color: Color { + a: 0.7, + ..Color::BLACK + }, + selected_background: Color { + a: 0.5, + ..Color::BLACK + } + .into(), + selected_text_color: Color::WHITE, + } + } + + fn active(&self) -> pick_list::Style { + pick_list::Style { + text_color: Color::WHITE, + background: BACKGROUND.into(), + border_width: 1, + border_color: Color { + a: 0.6, + ..Color::BLACK + }, + border_radius: 2, + icon_size: 0.5, + } + } + + fn hovered(&self) -> pick_list::Style { + let active = self.active(); + + pick_list::Style { + border_color: Color { + a: 0.9, + ..Color::BLACK + }, + ..active + } + } +} -- cgit From 26fbc9af0097f7f912c554b3a1e0281678bb4823 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 08:11:31 +0200 Subject: Simplify `pick_list` example --- examples/pick_list/src/main.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'examples') diff --git a/examples/pick_list/src/main.rs b/examples/pick_list/src/main.rs index 4eb368d1..66ed6c6f 100644 --- a/examples/pick_list/src/main.rs +++ b/examples/pick_list/src/main.rs @@ -1,6 +1,6 @@ use iced::{ - button, pick_list, scrollable, Align, Button, Container, Element, Length, - PickList, Sandbox, Scrollable, Settings, Space, Text, + pick_list, scrollable, Align, Container, Element, Length, PickList, + Sandbox, Scrollable, Settings, Space, Text, }; pub fn main() { @@ -10,14 +10,12 @@ pub fn main() { #[derive(Default)] struct Example { scroll: scrollable::State, - button: button::State, pick_list: pick_list::State, selected_language: Language, } #[derive(Debug, Clone, Copy)] enum Message { - ButtonPressed, LanguageSelected(Language), } @@ -34,7 +32,6 @@ impl Sandbox for Example { fn update(&mut self, message: Message) { match message { - Message::ButtonPressed => {} Message::LanguageSelected(language) => { self.selected_language = language; } @@ -49,20 +46,15 @@ impl Sandbox for Example { Message::LanguageSelected, ); - let button = Button::new(&mut self.button, Text::new("Press me!")) - .on_press(Message::ButtonPressed); - let mut content = Scrollable::new(&mut self.scroll) .width(Length::Fill) .align_items(Align::Center) .spacing(10) - .push(Space::with_height(Length::Units(800))) + .push(Space::with_height(Length::Units(600))) .push(Text::new("Which is your favorite language?")) .push(pick_list); - content = content - .push(button) - .push(Space::with_height(Length::Units(800))); + content = content.push(Space::with_height(Length::Units(600))); Container::new(content) .width(Length::Fill) -- cgit From 73d1353976e508d918206e2f61b6f45f551e0ff8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 16 Jul 2020 04:30:06 +0200 Subject: Update `README` of examples --- examples/README.md | 1 + examples/pick_list/README.md | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'examples') diff --git a/examples/README.md b/examples/README.md index 8e1b781f..34a916a1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -100,6 +100,7 @@ A bunch of simpler examples exist: - [`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. +- [`pick_list`](pick_list), a dropdown list of selectable options. - [`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/pick_list/README.md b/examples/pick_list/README.md index 4d9fc5b9..6dc80bf4 100644 --- a/examples/pick_list/README.md +++ b/examples/pick_list/README.md @@ -1,18 +1,18 @@ -## Counter +## Pick-list -The classic counter example explained in the [`README`](../../README.md). +A dropdown list of selectable options. + +It displays and positions an overlay based on the window position of the widget. The __[`main`]__ file contains all the code of the example.
- - - +
You can run it with `cargo run`: ``` -cargo run --package counter +cargo run --package pick_list ``` [`main`]: src/main.rs -- cgit