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: --- native/src/widget/button.rs | 2 +- native/src/widget/checkbox.rs | 2 +- native/src/widget/column.rs | 2 +- native/src/widget/container.rs | 2 +- native/src/widget/image.rs | 2 +- native/src/widget/pane_grid.rs | 2 +- native/src/widget/progress_bar.rs | 3 ++- native/src/widget/radio.rs | 3 ++- native/src/widget/row.rs | 2 +- native/src/widget/scrollable.rs | 2 +- native/src/widget/slider.rs | 2 +- native/src/widget/space.rs | 2 +- native/src/widget/svg.rs | 2 +- native/src/widget/text.rs | 2 +- native/src/widget/text_input.rs | 2 +- 15 files changed, 17 insertions(+), 15 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index c932da2b..72db808b 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -139,7 +139,7 @@ impl State { } } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Button<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 44962288..82fd6d1f 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -106,7 +106,7 @@ impl } } -impl Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Checkbox where Renderer: self::Renderer + text::Renderer + row::Renderer, diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 259a7e6e..6afc94d6 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -121,7 +121,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Column<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 2590fe3b..3ad12eeb 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -129,7 +129,7 @@ where } } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Container<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 132f249d..b7c8f4ff 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -54,7 +54,7 @@ impl Image { } } -impl Widget for Image +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Image where Renderer: self::Renderer, { diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index a8deef0b..faf8da4e 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -387,7 +387,7 @@ pub struct KeyPressEvent { pub modifiers: keyboard::ModifiersState, } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for PaneGrid<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 5ab76d47..93d86371 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -70,7 +70,8 @@ impl ProgressBar { } } -impl Widget for ProgressBar +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> + for ProgressBar where Renderer: self::Renderer, { diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 5b8d00e9..0d88c740 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -121,7 +121,8 @@ impl } } -impl Widget for Radio +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> + for Radio where Renderer: self::Renderer + text::Renderer + row::Renderer, Message: Clone, diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 31f7472f..1ebbac6b 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -122,7 +122,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Row<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 3c8e5e5b..d7ad98e6 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -110,7 +110,7 @@ impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Scrollable<'a, Message, Renderer> where Renderer: self::Renderer + column::Renderer, diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 70f2b6ac..e0193342 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -154,7 +154,7 @@ impl State { } } -impl<'a, T, Message, Renderer> Widget +impl<'a, T, Message, Renderer> Widget<'a, Message, Renderer> for Slider<'a, T, Message, Renderer> where T: Copy + Into + num_traits::FromPrimitive, diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index e56a8fe1..8ada40ed 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -43,7 +43,7 @@ impl Space { } } -impl<'a, Message, Renderer> Widget for Space +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Space where Renderer: self::Renderer, { diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 114d5e41..3e45aaf6 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -60,7 +60,7 @@ impl Svg { } } -impl Widget for Svg +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Svg where Renderer: self::Renderer, { diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 48a69e34..7f75eb9c 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -112,7 +112,7 @@ impl Text { } } -impl Widget for Text +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Text where Renderer: self::Renderer, { diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 3f415101..63be6019 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -165,7 +165,7 @@ impl<'a, Message, Renderer: self::Renderer> TextInput<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget +impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for TextInput<'a, Message, Renderer> where Renderer: self::Renderer, -- cgit From f064f0482b653a1fbee4afbddcecf91e3a399004 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 16 Apr 2020 13:22:00 +0200 Subject: Introduce `Layer` trait --- native/src/widget/column.rs | 15 +++++++++++++-- native/src/widget/container.rs | 11 +++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 6afc94d6..9a6dbdb3 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -2,8 +2,8 @@ use std::hash::Hash; use crate::{ - layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, - Widget, + layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Overlay, + Point, Widget, }; use std::u32; @@ -204,6 +204,17 @@ where child.widget.hash_layout(state); } } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + self.children + .iter_mut() + .zip(layout.children()) + .filter_map(|(child, layout)| child.widget.overlay(layout)) + .next() + } } /// The renderer of a [`Column`]. diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 3ad12eeb..3bdb1a27 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -2,8 +2,8 @@ use std::hash::Hash; use crate::{ - layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, - Rectangle, Widget, + layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Overlay, + Point, Rectangle, Widget, }; use std::u32; @@ -214,6 +214,13 @@ where self.content.hash_layout(state); } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + self.content.overlay(layout.children().next().unwrap()) + } } /// The renderer of a [`Container`]. -- 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 --- native/src/widget/combo_box.rs | 256 ++++++++++++++++++++++++++++++++++++++++ native/src/widget/scrollable.rs | 6 +- 2 files changed, 259 insertions(+), 3 deletions(-) create mode 100644 native/src/widget/combo_box.rs (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs new file mode 100644 index 00000000..0b25b836 --- /dev/null +++ b/native/src/widget/combo_box.rs @@ -0,0 +1,256 @@ +use crate::{ + layer::{self, menu}, + layout, mouse, scrollable, text, Clipboard, Element, Event, Hasher, Layout, + Length, Overlay, Point, Rectangle, Size, Vector, Widget, +}; +use std::borrow::Cow; + +pub struct ComboBox<'a, T, Message> +where + [T]: ToOwned>, +{ + internal: Option>, + options: Cow<'a, [T]>, + selected: Option, + width: Length, + padding: u16, + text_size: Option, +} + +#[derive(Default)] +pub struct State { + menu: menu::State, +} + +pub struct Internal<'a, T, Message> { + menu: &'a mut menu::State, + on_selected: Box Message>, +} + +impl<'a, T: 'a, Message> ComboBox<'a, T, Message> +where + T: ToString, + [T]: ToOwned>, +{ + pub fn new( + state: &'a mut State, + options: impl Into>, + selected: Option, + on_selected: impl Fn(T) -> Message + 'static, + ) -> Self { + Self { + internal: Some(Internal { + menu: &mut state.menu, + on_selected: Box::new(on_selected), + }), + options: options.into(), + selected, + width: Length::Shrink, + text_size: None, + padding: 5, + } + } + + /// Sets the width of the [`ComboBox`]. + /// + /// [`ComboBox`]: struct.Button.html + pub fn width(mut self, width: Length) -> Self { + self.width = width; + self + } + + /// Sets the padding of the [`ComboBox`]. + /// + /// [`ComboBox`]: struct.Button.html + pub fn padding(mut self, padding: u16) -> Self { + self.padding = padding; + self + } + + pub fn text_size(mut self, size: u16) -> Self { + self.text_size = Some(size); + self + } +} + +impl<'a, T: 'a, Message, Renderer> Widget<'a, Message, Renderer> + for ComboBox<'a, T, Message> +where + T: Clone + ToString + Eq, + [T]: ToOwned>, + Message: 'static, + Renderer: self::Renderer + scrollable::Renderer + 'a, +{ + fn width(&self) -> Length { + Length::Shrink + } + + fn height(&self) -> Length { + Length::Shrink + } + + fn layout( + &self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + use std::f32; + + let limits = limits + .width(self.width) + .height(Length::Shrink) + .pad(f32::from(self.padding)); + + let text_size = self.text_size.unwrap_or(renderer.default_size()); + + let max_width = match self.width { + Length::Shrink => { + let labels = self.options.iter().map(ToString::to_string); + + labels + .map(|label| { + let (width, _) = renderer.measure( + &label, + text_size, + Renderer::Font::default(), + Size::new(f32::INFINITY, f32::INFINITY), + ); + + width.round() as u32 + }) + .max() + .unwrap_or(100) + } + _ => 0, + }; + + let size = { + let intrinsic = Size::new( + max_width as f32 + f32::from(text_size), + f32::from(text_size), + ); + + limits.resolve(intrinsic).pad(f32::from(self.padding)) + }; + + layout::Node::new(size) + } + + fn hash_layout(&self, state: &mut Hasher) { + use std::hash::Hash as _; + + match self.width { + Length::Shrink => { + self.options + .iter() + .map(ToString::to_string) + .for_each(|label| label.hash(state)); + } + _ => { + self.width.hash(state); + } + } + } + + fn on_event( + &mut self, + event: Event, + layout: Layout<'_>, + cursor_position: Point, + _messages: &mut Vec, + _renderer: &Renderer, + _clipboard: Option<&dyn Clipboard>, + ) { + match event { + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { + if let Some(internal) = &mut self.internal { + if layout.bounds().contains(cursor_position) { + let selected = self.selected.as_ref(); + + internal.menu.open( + self.options + .iter() + .position(|option| Some(option) == selected), + ); + } + } + } + _ => {} + } + } + + fn draw( + &self, + renderer: &mut Renderer, + _defaults: &Renderer::Defaults, + layout: Layout<'_>, + cursor_position: Point, + ) -> Renderer::Output { + self::Renderer::draw( + renderer, + layout.bounds(), + cursor_position, + self.selected.as_ref().map(ToString::to_string), + self.text_size.unwrap_or(renderer.default_size()), + self.padding, + ) + } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + let is_open = self + .internal + .as_ref() + .map(|internal| internal.menu.is_open()) + .unwrap_or(false); + + if is_open { + if let Some(Internal { menu, on_selected }) = self.internal.take() { + Some(Overlay::new( + layout.position() + + Vector::new(0.0, layout.bounds().height), + Box::new(layer::Menu::new( + menu, + self.options.clone(), + on_selected, + layout.bounds().width.round() as u16, + self.text_size.unwrap_or(20), + self.padding, + )), + )) + } else { + None + } + } else { + None + } + } +} + +pub trait Renderer: text::Renderer + menu::Renderer { + const DEFAULT_PADDING: u16; + + fn draw( + &mut self, + bounds: Rectangle, + cursor_position: Point, + selected: Option, + text_size: u16, + padding: u16, + ) -> Self::Output; +} + +impl<'a, T: 'a, Message, Renderer> Into> + for ComboBox<'a, T, Message> +where + T: Clone + ToString + Eq, + [T]: ToOwned>, + Renderer: self::Renderer + 'a, + Message: 'static, +{ + fn into(self) -> Element<'a, Message, Renderer> { + Element::new(self) + } +} diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index d7ad98e6..25fd8982 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -113,7 +113,7 @@ impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Scrollable<'a, Message, Renderer> where - Renderer: self::Renderer + column::Renderer, + Renderer: self::Renderer, { fn width(&self) -> Length { Widget::::width(&self.content) @@ -454,7 +454,7 @@ pub struct Scroller { /// /// [`Scrollable`]: struct.Scrollable.html /// [renderer]: ../../renderer/index.html -pub trait Renderer: crate::Renderer + Sized { +pub trait Renderer: column::Renderer + Sized { /// The style supported by this renderer. type Style: Default; @@ -502,7 +502,7 @@ pub trait Renderer: crate::Renderer + Sized { impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + column::Renderer, + Renderer: 'a + self::Renderer, Message: 'a, { fn from( -- 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` --- native/src/widget/scrollable.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 25fd8982..92e5265a 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -1,7 +1,7 @@ //! Navigate an endless amount of content with a scrollbar. use crate::{ column, layout, mouse, Align, Clipboard, Column, Element, Event, Hasher, - Layout, Length, Point, Rectangle, Size, Widget, + Layout, Length, Overlay, Point, Rectangle, Size, Vector, Widget, }; use std::{f32, hash::Hash, u32}; @@ -315,6 +315,22 @@ where self.content.hash_layout(state) } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + self.content + .overlay(layout.children().next().unwrap()) + .map(|overlay| { + let bounds = layout.bounds(); + let content_layout = layout.children().next().unwrap(); + let content_bounds = content_layout.bounds(); + let offset = self.state.offset(bounds, content_bounds); + + overlay.translate(Vector::new(0.0, -(offset as f32))) + }) + } } /// The local state of a [`Scrollable`]. -- cgit From e29feef8ba4f95f286039fcc1ca2e53bfe5019c5 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 18 Apr 2020 19:53:27 +0200 Subject: Render arrow icon in `ComboBox` --- native/src/widget/combo_box.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 0b25b836..1b04a9a8 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -126,7 +126,9 @@ where let size = { let intrinsic = Size::new( - max_width as f32 + f32::from(text_size), + max_width as f32 + + f32::from(text_size) + + f32::from(self.padding), f32::from(text_size), ); -- 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 --- native/src/widget/combo_box.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 1b04a9a8..0f249282 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -1,7 +1,7 @@ use crate::{ layer::{self, menu}, layout, mouse, scrollable, text, Clipboard, Element, Event, Hasher, Layout, - Length, Overlay, Point, Rectangle, Size, Vector, Widget, + Length, Overlay, Point, Rectangle, Size, Widget, }; use std::borrow::Cow; @@ -210,14 +210,16 @@ where if is_open { if let Some(Internal { menu, on_selected }) = self.internal.take() { + let bounds = layout.bounds(); + Some(Overlay::new( - layout.position() - + Vector::new(0.0, layout.bounds().height), + layout.position(), Box::new(layer::Menu::new( menu, self.options.clone(), on_selected, - layout.bounds().width.round() as u16, + bounds.width.round() as u16, + bounds.height, self.text_size.unwrap_or(20), self.padding, )), -- cgit From a2642366240f64f0699fe5fc048b99ace2031751 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 7 May 2020 01:33:11 +0200 Subject: Implement `Widget::overlay` for `Row` --- native/src/widget/row.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 1ebbac6b..25bd641f 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -2,8 +2,8 @@ use std::hash::Hash; use crate::{ - layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, - Widget, + layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Overlay, + Point, Widget, }; use std::u32; @@ -206,6 +206,17 @@ where child.widget.hash_layout(state); } } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + self.children + .iter_mut() + .zip(layout.children()) + .filter_map(|(child, layout)| child.widget.overlay(layout)) + .next() + } } /// The renderer of a [`Row`]. -- cgit From 0ff5a02550e5d5de8fb5fd0643ea424d9e508888 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 23 May 2020 01:07:59 +0200 Subject: Rename `Layer` to `overlay::Content` --- native/src/widget/combo_box.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 0f249282..2adee884 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -1,7 +1,8 @@ use crate::{ - layer::{self, menu}, - layout, mouse, scrollable, text, Clipboard, Element, Event, Hasher, Layout, - Length, Overlay, Point, Rectangle, Size, Widget, + layout, mouse, + overlay::menu::{self, Menu}, + scrollable, text, Clipboard, Element, Event, Hasher, Layout, Length, + Overlay, Point, Rectangle, Size, Widget, }; use std::borrow::Cow; @@ -214,7 +215,7 @@ where Some(Overlay::new( layout.position(), - Box::new(layer::Menu::new( + Box::new(Menu::new( menu, self.options.clone(), on_selected, -- cgit From 61f22b1db23f3495145a9a4f7255311fe8381998 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 11 Jun 2020 20:41:11 +0200 Subject: Add styling support for `ComboBox` and `Menu` --- native/src/widget/combo_box.rs | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 2adee884..df2a530a 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -6,7 +6,7 @@ use crate::{ }; use std::borrow::Cow; -pub struct ComboBox<'a, T, Message> +pub struct ComboBox<'a, T, Message, Renderer: self::Renderer> where [T]: ToOwned>, { @@ -16,6 +16,7 @@ where width: Length, padding: u16, text_size: Option, + style: ::Style, } #[derive(Default)] @@ -28,7 +29,8 @@ pub struct Internal<'a, T, Message> { on_selected: Box Message>, } -impl<'a, T: 'a, Message> ComboBox<'a, T, Message> +impl<'a, T: 'a, Message, Renderer: self::Renderer> + ComboBox<'a, T, Message, Renderer> where T: ToString, [T]: ToOwned>, @@ -48,7 +50,8 @@ where selected, width: Length::Shrink, text_size: None, - padding: 5, + padding: Renderer::DEFAULT_PADDING, + style: ::Style::default(), } } @@ -72,10 +75,21 @@ where self.text_size = Some(size); self } + + /// Sets the style of the [`ComboBox`]. + /// + /// [`ComboBox`]: struct.ComboBox.html + pub fn style( + mut self, + style: impl Into<::Style>, + ) -> Self { + self.style = style.into(); + self + } } impl<'a, T: 'a, Message, Renderer> Widget<'a, Message, Renderer> - for ComboBox<'a, T, Message> + for ComboBox<'a, T, Message, Renderer> where T: Clone + ToString + Eq, [T]: ToOwned>, @@ -196,6 +210,7 @@ where self.selected.as_ref().map(ToString::to_string), self.text_size.unwrap_or(renderer.default_size()), self.padding, + &self.style, ) } @@ -223,6 +238,7 @@ where bounds.height, self.text_size.unwrap_or(20), self.padding, + Renderer::menu_style(&self.style), )), )) } else { @@ -235,8 +251,14 @@ where } pub trait Renderer: text::Renderer + menu::Renderer { + type Style: Default; + const DEFAULT_PADDING: u16; + fn menu_style( + style: &::Style, + ) -> ::Style; + fn draw( &mut self, bounds: Rectangle, @@ -244,11 +266,12 @@ pub trait Renderer: text::Renderer + menu::Renderer { selected: Option, text_size: u16, padding: u16, + style: &::Style, ) -> Self::Output; } impl<'a, T: 'a, Message, Renderer> Into> - for ComboBox<'a, T, Message> + for ComboBox<'a, T, Message, Renderer> where T: Clone + ToString + Eq, [T]: ToOwned>, -- cgit From 625979b6652a8a14a0eaf6bd62f1e9a8da0ae421 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 5 Jul 2020 05:44:10 +0200 Subject: Draft `Widget::overlay` idempotency --- native/src/widget/column.rs | 2 +- native/src/widget/combo_box.rs | 68 +++++++++++++++++------------------------ native/src/widget/container.rs | 2 +- native/src/widget/row.rs | 2 +- native/src/widget/scrollable.rs | 8 +++-- 5 files changed, 36 insertions(+), 46 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 9a6dbdb3..e83ef93d 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -208,7 +208,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { self.children .iter_mut() .zip(layout.children()) diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index df2a530a..4a509354 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -10,7 +10,7 @@ pub struct ComboBox<'a, T, Message, Renderer: self::Renderer> where [T]: ToOwned>, { - internal: Option>, + internal: Internal<'a, T, Message>, options: Cow<'a, [T]>, selected: Option, width: Length, @@ -42,10 +42,10 @@ where on_selected: impl Fn(T) -> Message + 'static, ) -> Self { Self { - internal: Some(Internal { + internal: Internal { menu: &mut state.menu, on_selected: Box::new(on_selected), - }), + }, options: options.into(), selected, width: Length::Shrink, @@ -180,16 +180,14 @@ where ) { match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { - if let Some(internal) = &mut self.internal { - if layout.bounds().contains(cursor_position) { - let selected = self.selected.as_ref(); - - internal.menu.open( - self.options - .iter() - .position(|option| Some(option) == selected), - ); - } + if layout.bounds().contains(cursor_position) { + let selected = self.selected.as_ref(); + + self.internal.menu.open( + self.options + .iter() + .position(|option| Some(option) == selected), + ); } } _ => {} @@ -217,33 +215,23 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { - let is_open = self - .internal - .as_ref() - .map(|internal| internal.menu.is_open()) - .unwrap_or(false); - - if is_open { - if let Some(Internal { menu, on_selected }) = self.internal.take() { - let bounds = layout.bounds(); - - Some(Overlay::new( - layout.position(), - Box::new(Menu::new( - menu, - self.options.clone(), - on_selected, - bounds.width.round() as u16, - bounds.height, - self.text_size.unwrap_or(20), - self.padding, - Renderer::menu_style(&self.style), - )), - )) - } else { - None - } + ) -> Option> { + if self.internal.menu.is_open() { + let bounds = layout.bounds(); + + Some(Overlay::new( + layout.position(), + Box::new(Menu::new( + self.internal.menu, + self.options.clone(), + &self.internal.on_selected, + bounds.width.round() as u16, + bounds.height, + self.text_size, + self.padding, + Renderer::menu_style(&self.style), + )), + )) } else { None } diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 3bdb1a27..4ab10837 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -218,7 +218,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { self.content.overlay(layout.children().next().unwrap()) } } diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 25bd641f..1cfe2d66 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -210,7 +210,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { self.children .iter_mut() .zip(layout.children()) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 92e5265a..87871e28 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -319,14 +319,16 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { - self.content + ) -> Option> { + let Self { content, state, .. } = self; + + content .overlay(layout.children().next().unwrap()) .map(|overlay| { let bounds = layout.bounds(); let content_layout = layout.children().next().unwrap(); let content_bounds = content_layout.bounds(); - let offset = self.state.offset(bounds, content_bounds); + let offset = state.offset(bounds, content_bounds); overlay.translate(Vector::new(0.0, -(offset as f32))) }) -- cgit From 7a105ade27c7f33397e3050280e9faef928bdc1b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 8 Jul 2020 06:14:57 +0200 Subject: Use `Borrow` to avoid clone in `ComboBox::overlay` --- native/src/widget/combo_box.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 4a509354..f2dc86e8 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -223,7 +223,7 @@ where layout.position(), Box::new(Menu::new( self.internal.menu, - self.options.clone(), + &self.options, &self.internal.on_selected, bounds.width.round() as u16, bounds.height, -- cgit From 1c12bad866d06b320f16609576d5937413418a0c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 8 Jul 2020 06:55:22 +0200 Subject: Split `Menu::new` into multiple builder methods --- native/src/widget/combo_box.rs | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index f2dc86e8..f6da076a 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -10,7 +10,8 @@ pub struct ComboBox<'a, T, Message, Renderer: self::Renderer> where [T]: ToOwned>, { - internal: Internal<'a, T, Message>, + menu: &'a mut menu::State, + on_selected: Box Message>, options: Cow<'a, [T]>, selected: Option, width: Length, @@ -24,11 +25,6 @@ pub struct State { menu: menu::State, } -pub struct Internal<'a, T, Message> { - menu: &'a mut menu::State, - on_selected: Box Message>, -} - impl<'a, T: 'a, Message, Renderer: self::Renderer> ComboBox<'a, T, Message, Renderer> where @@ -42,10 +38,8 @@ where on_selected: impl Fn(T) -> Message + 'static, ) -> Self { Self { - internal: Internal { - menu: &mut state.menu, - on_selected: Box::new(on_selected), - }, + menu: &mut state.menu, + on_selected: Box::new(on_selected), options: options.into(), selected, width: Length::Shrink, @@ -183,7 +177,7 @@ where if layout.bounds().contains(cursor_position) { let selected = self.selected.as_ref(); - self.internal.menu.open( + self.menu.open( self.options .iter() .position(|option| Some(option) == selected), @@ -216,22 +210,20 @@ where &mut self, layout: Layout<'_>, ) -> Option> { - if self.internal.menu.is_open() { + if self.menu.is_open() { let bounds = layout.bounds(); - Some(Overlay::new( - layout.position(), - Box::new(Menu::new( - self.internal.menu, - &self.options, - &self.internal.on_selected, - bounds.width.round() as u16, - bounds.height, - self.text_size, - self.padding, - Renderer::menu_style(&self.style), - )), - )) + let mut menu = + Menu::new(&mut self.menu, &self.options, &self.on_selected) + .width(bounds.width.round() as u16) + .padding(self.padding) + .style(Renderer::menu_style(&self.style)); + + if let Some(text_size) = self.text_size { + menu = menu.text_size(text_size); + } + + Some(menu.overlay(layout.position(), bounds.height)) } else { None } -- cgit From 69ac47f463fd5c392f1f8e788fcf89b1a76abcae Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 8 Jul 2020 07:04:20 +0200 Subject: Implement `font` method for `ComboBox` --- native/src/widget/combo_box.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index f6da076a..84789789 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -17,6 +17,7 @@ where width: Length, padding: u16, text_size: Option, + font: Renderer::Font, style: ::Style, } @@ -45,7 +46,8 @@ where width: Length::Shrink, text_size: None, padding: Renderer::DEFAULT_PADDING, - style: ::Style::default(), + font: Default::default(), + style: Default::default(), } } @@ -70,6 +72,11 @@ where self } + pub fn font(mut self, font: Renderer::Font) -> Self { + self.font = font; + self + } + /// Sets the style of the [`ComboBox`]. /// /// [`ComboBox`]: struct.ComboBox.html @@ -200,8 +207,9 @@ where layout.bounds(), cursor_position, self.selected.as_ref().map(ToString::to_string), - self.text_size.unwrap_or(renderer.default_size()), self.padding, + self.text_size.unwrap_or(renderer.default_size()), + self.font, &self.style, ) } @@ -244,8 +252,9 @@ pub trait Renderer: text::Renderer + menu::Renderer { bounds: Rectangle, cursor_position: Point, selected: Option, - text_size: u16, padding: u16, + text_size: u16, + font: Self::Font, style: &::Style, ) -> Self::Output; } -- cgit From 105c0fe4780233670191abe50ddc922a553ffd63 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 8 Jul 2020 08:19:26 +0200 Subject: Propagate `Font` from `ComboBox` to `Menu` --- native/src/widget/combo_box.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 84789789..4d020c3b 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -225,6 +225,7 @@ where Menu::new(&mut self.menu, &self.options, &self.on_selected) .width(bounds.width.round() as u16) .padding(self.padding) + .font(self.font) .style(Renderer::menu_style(&self.style)); if let Some(text_size) = self.text_size { -- cgit From 21b583c46899d8f31ea39ede7194abf6f61df636 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 8 Jul 2020 08:25:56 +0200 Subject: Avoid reopening `Menu` in `ComboBox` --- native/src/widget/combo_box.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 4d020c3b..9447b9dd 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -19,6 +19,7 @@ where text_size: Option, font: Renderer::Font, style: ::Style, + is_open: bool, } #[derive(Default)] @@ -38,6 +39,8 @@ where selected: Option, on_selected: impl Fn(T) -> Message + 'static, ) -> Self { + let is_open = state.menu.is_open(); + Self { menu: &mut state.menu, on_selected: Box::new(on_selected), @@ -48,6 +51,7 @@ where padding: Renderer::DEFAULT_PADDING, font: Default::default(), style: Default::default(), + is_open, } } @@ -179,19 +183,23 @@ where _renderer: &Renderer, _clipboard: Option<&dyn Clipboard>, ) { - match event { - Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { - if layout.bounds().contains(cursor_position) { - let selected = self.selected.as_ref(); - - self.menu.open( - self.options - .iter() - .position(|option| Some(option) == selected), - ); + if !self.is_open { + match event { + Event::Mouse(mouse::Event::ButtonPressed( + mouse::Button::Left, + )) => { + if layout.bounds().contains(cursor_position) { + let selected = self.selected.as_ref(); + + self.menu.open( + self.options + .iter() + .position(|option| Some(option) == selected), + ); + } } + _ => {} } - _ => {} } } -- cgit From 1070b61f3408539f6c9cb9d265f3295e6d055db7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 01:31:56 +0200 Subject: Rename `overlay::Content` trait to `Overlay` The `Overlay` struct is now `overlay::Element`. --- native/src/widget/column.rs | 4 ++-- native/src/widget/combo_box.rs | 8 ++++---- native/src/widget/container.rs | 4 ++-- native/src/widget/row.rs | 4 ++-- native/src/widget/scrollable.rs | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index e83ef93d..83d5054f 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -2,7 +2,7 @@ use std::hash::Hash; use crate::{ - layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Overlay, + layout, overlay, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, Widget, }; @@ -208,7 +208,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { self.children .iter_mut() .zip(layout.children()) diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index 9447b9dd..e33eebfd 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -1,8 +1,8 @@ use crate::{ - layout, mouse, + layout, mouse, overlay, overlay::menu::{self, Menu}, - scrollable, text, Clipboard, Element, Event, Hasher, Layout, Length, - Overlay, Point, Rectangle, Size, Widget, + scrollable, text, Clipboard, Element, Event, Hasher, Layout, Length, Point, + Rectangle, Size, Widget, }; use std::borrow::Cow; @@ -225,7 +225,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { if self.menu.is_open() { let bounds = layout.bounds(); diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 4ab10837..0ee67db0 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -2,7 +2,7 @@ use std::hash::Hash; use crate::{ - layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Overlay, + layout, overlay, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, Rectangle, Widget, }; @@ -218,7 +218,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { self.content.overlay(layout.children().next().unwrap()) } } diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 1cfe2d66..eda515b0 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -2,7 +2,7 @@ use std::hash::Hash; use crate::{ - layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Overlay, + layout, overlay, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, Widget, }; @@ -210,7 +210,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { self.children .iter_mut() .zip(layout.children()) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 87871e28..abd8cfbd 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -1,7 +1,7 @@ //! Navigate an endless amount of content with a scrollbar. use crate::{ - column, layout, mouse, Align, Clipboard, Column, Element, Event, Hasher, - Layout, Length, Overlay, Point, Rectangle, Size, Vector, Widget, + column, layout, mouse, overlay, Align, Clipboard, Column, Element, Event, + Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, }; use std::{f32, hash::Hash, u32}; @@ -319,7 +319,7 @@ where fn overlay( &mut self, layout: Layout<'_>, - ) -> Option> { + ) -> Option> { let Self { content, state, .. } = self; content -- cgit From f24e03eae85cb4a684eb0a28033c70c355d2c5ca Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 01:35:58 +0200 Subject: Implement `Widget::overlay` for `PaneGrid` --- native/src/widget/pane_grid.rs | 15 +++++++++++++-- native/src/widget/pane_grid/content.rs | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 8fc423af..a8e1f852 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -29,8 +29,8 @@ pub use state::{Focus, State}; pub use title_bar::TitleBar; use crate::{ - container, keyboard, layout, mouse, row, text, Clipboard, Element, Event, - Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, + container, keyboard, layout, mouse, overlay, row, text, Clipboard, Element, + Event, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, }; /// A collection of panes distributed using either vertical or horizontal splits @@ -636,6 +636,17 @@ where element.hash_layout(state); } } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + self.elements + .iter_mut() + .zip(layout.children()) + .filter_map(|((_, pane), layout)| pane.overlay(layout)) + .next() + } } /// The renderer of a [`PaneGrid`]. diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index 1f5ce640..39a92186 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -1,5 +1,6 @@ use crate::container; use crate::layout; +use crate::overlay; use crate::pane_grid::{self, TitleBar}; use crate::{Clipboard, Element, Event, Hasher, Layout, Point, Size}; @@ -184,6 +185,24 @@ where pub(crate) fn hash_layout(&self, state: &mut Hasher) { self.body.hash_layout(state); } + + pub(crate) fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + let body_layout = if self.title_bar.is_some() { + let mut children = layout.children(); + + // Overlays only allowed in the pane body, for now at least. + let _title_bar_layout = children.next(); + + children.next()? + } else { + layout + }; + + self.body.overlay(body_layout) + } } impl<'a, T, Message, Renderer> From for Content<'a, Message, Renderer> -- 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 --- native/src/widget/button.rs | 2 +- native/src/widget/checkbox.rs | 2 +- native/src/widget/column.rs | 2 +- native/src/widget/combo_box.rs | 2 +- native/src/widget/container.rs | 2 +- native/src/widget/image.rs | 2 +- native/src/widget/pane_grid.rs | 2 +- native/src/widget/progress_bar.rs | 3 +-- native/src/widget/radio.rs | 3 +-- native/src/widget/row.rs | 2 +- native/src/widget/scrollable.rs | 2 +- native/src/widget/slider.rs | 2 +- native/src/widget/space.rs | 2 +- native/src/widget/svg.rs | 2 +- native/src/widget/text.rs | 2 +- native/src/widget/text_input.rs | 2 +- 16 files changed, 16 insertions(+), 18 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 72db808b..c932da2b 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -139,7 +139,7 @@ impl State { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for Button<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 82fd6d1f..44962288 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -106,7 +106,7 @@ impl } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl Widget for Checkbox where Renderer: self::Renderer + text::Renderer + row::Renderer, diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 83d5054f..42cfe9b9 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -121,7 +121,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for Column<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index e33eebfd..a9f0e6ed 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -93,7 +93,7 @@ where } } -impl<'a, T: 'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, T: 'a, Message, Renderer> Widget for ComboBox<'a, T, Message, Renderer> where T: Clone + ToString + Eq, diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 0ee67db0..b8316e62 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -129,7 +129,7 @@ where } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for Container<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index b7c8f4ff..132f249d 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -54,7 +54,7 @@ impl Image { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Image +impl Widget for Image where Renderer: self::Renderer, { diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index a8e1f852..0b237b9e 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -402,7 +402,7 @@ pub struct KeyPressEvent { pub modifiers: keyboard::ModifiersState, } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for PaneGrid<'a, Message, Renderer> where Renderer: self::Renderer + container::Renderer, diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index 93d86371..5ab76d47 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -70,8 +70,7 @@ impl ProgressBar { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> - for ProgressBar +impl Widget for ProgressBar where Renderer: self::Renderer, { diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 0d88c740..5b8d00e9 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -121,8 +121,7 @@ impl } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> - for Radio +impl Widget for Radio where Renderer: self::Renderer + text::Renderer + row::Renderer, Message: Clone, diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index eda515b0..2b6db224 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -122,7 +122,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for Row<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index abd8cfbd..75e97027 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -110,7 +110,7 @@ impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for Scrollable<'a, Message, Renderer> where Renderer: self::Renderer, diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index e0193342..70f2b6ac 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -154,7 +154,7 @@ impl State { } } -impl<'a, T, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, T, Message, Renderer> Widget for Slider<'a, T, Message, Renderer> where T: Copy + Into + num_traits::FromPrimitive, diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index 8ada40ed..f1576ffb 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -43,7 +43,7 @@ impl Space { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Space +impl Widget for Space where Renderer: self::Renderer, { diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index 3e45aaf6..114d5e41 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -60,7 +60,7 @@ impl Svg { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Svg +impl Widget for Svg where Renderer: self::Renderer, { diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 7f75eb9c..48a69e34 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -112,7 +112,7 @@ impl Text { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> for Text +impl Widget for Text where Renderer: self::Renderer, { diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 63be6019..3f415101 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -165,7 +165,7 @@ impl<'a, Message, Renderer: self::Renderer> TextInput<'a, Message, Renderer> { } } -impl<'a, Message, Renderer> Widget<'a, Message, Renderer> +impl<'a, Message, Renderer> Widget for TextInput<'a, Message, Renderer> where Renderer: self::Renderer, -- cgit From 2118a726f8b6134820e1ca5b7b802fa1344e453a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 10 Jul 2020 02:39:12 +0200 Subject: Write documentation for the new `overlay` API --- native/src/widget/combo_box.rs | 48 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs index a9f0e6ed..fefaf8ff 100644 --- a/native/src/widget/combo_box.rs +++ b/native/src/widget/combo_box.rs @@ -1,3 +1,4 @@ +//! Display a dropdown list of selectable values. use crate::{ layout, mouse, overlay, overlay::menu::{self, Menu}, @@ -6,6 +7,8 @@ use crate::{ }; use std::borrow::Cow; +/// A widget for selecting a single value from a list of options. +#[allow(missing_debug_implementations)] pub struct ComboBox<'a, T, Message, Renderer: self::Renderer> where [T]: ToOwned>, @@ -22,7 +25,10 @@ where is_open: bool, } -#[derive(Default)] +/// The local state of a [`ComboBox`]. +/// +/// [`ComboBox`]: struct.ComboBox.html +#[derive(Debug, Clone, Default)] pub struct State { menu: menu::State, } @@ -33,6 +39,12 @@ where T: ToString, [T]: ToOwned>, { + /// Creates a new [`ComboBox`] with the given [`State`], a list of options, + /// the current selected value, and the message to produce when an option is + /// selected. + /// + /// [`ComboBox`]: struct.ComboBox.html + /// [`State`]: struct.State.html pub fn new( state: &'a mut State, options: impl Into>, @@ -57,7 +69,7 @@ where /// Sets the width of the [`ComboBox`]. /// - /// [`ComboBox`]: struct.Button.html + /// [`ComboBox`]: struct.ComboBox.html pub fn width(mut self, width: Length) -> Self { self.width = width; self @@ -65,17 +77,23 @@ where /// Sets the padding of the [`ComboBox`]. /// - /// [`ComboBox`]: struct.Button.html + /// [`ComboBox`]: struct.ComboBox.html pub fn padding(mut self, padding: u16) -> Self { self.padding = padding; self } + /// Sets the text size of the [`ComboBox`]. + /// + /// [`ComboBox`]: struct.ComboBox.html pub fn text_size(mut self, size: u16) -> Self { self.text_size = Some(size); self } + /// Sets the font of the [`ComboBox`]. + /// + /// [`ComboBox`]: struct.ComboBox.html pub fn font(mut self, font: Renderer::Font) -> Self { self.font = font; self @@ -247,15 +265,35 @@ where } } +/// The renderer of a [`ComboBox`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`ComboBox`] in your user interface. +/// +/// [`ComboBox`]: struct.ComboBox.html +/// [renderer]: ../../renderer/index.html pub trait Renderer: text::Renderer + menu::Renderer { - type Style: Default; - + /// The default padding of a [`ComboBox`]. + /// + /// [`ComboBox`]: struct.ComboBox.html const DEFAULT_PADDING: u16; + /// The [`ComboBox`] style supported by this renderer. + /// + /// [`ComboBox`]: struct.ComboBox.html + type Style: Default; + + /// Returns the style of the [`Menu`] of the [`ComboBox`]. + /// + /// [`Menu`]: ../../overlay/menu/struct.Menu.html + /// [`ComboBox`]: struct.ComboBox.html fn menu_style( style: &::Style, ) -> ::Style; + /// Draws a [`ComboBox`]. + /// + /// [`ComboBox`]: struct.ComboBox.html fn draw( &mut self, bounds: Rectangle, -- 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` --- native/src/widget/combo_box.rs | 320 ----------------------------------------- native/src/widget/pick_list.rs | 320 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 320 insertions(+), 320 deletions(-) delete mode 100644 native/src/widget/combo_box.rs create mode 100644 native/src/widget/pick_list.rs (limited to 'native/src/widget') diff --git a/native/src/widget/combo_box.rs b/native/src/widget/combo_box.rs deleted file mode 100644 index fefaf8ff..00000000 --- a/native/src/widget/combo_box.rs +++ /dev/null @@ -1,320 +0,0 @@ -//! Display a dropdown list of selectable values. -use crate::{ - layout, mouse, overlay, - overlay::menu::{self, Menu}, - scrollable, text, Clipboard, Element, Event, Hasher, Layout, Length, Point, - Rectangle, Size, Widget, -}; -use std::borrow::Cow; - -/// A widget for selecting a single value from a list of options. -#[allow(missing_debug_implementations)] -pub struct ComboBox<'a, T, Message, Renderer: self::Renderer> -where - [T]: ToOwned>, -{ - menu: &'a mut menu::State, - on_selected: Box Message>, - options: Cow<'a, [T]>, - selected: Option, - width: Length, - padding: u16, - text_size: Option, - font: Renderer::Font, - style: ::Style, - is_open: bool, -} - -/// The local state of a [`ComboBox`]. -/// -/// [`ComboBox`]: struct.ComboBox.html -#[derive(Debug, Clone, Default)] -pub struct State { - menu: menu::State, -} - -impl<'a, T: 'a, Message, Renderer: self::Renderer> - ComboBox<'a, T, Message, Renderer> -where - T: ToString, - [T]: ToOwned>, -{ - /// Creates a new [`ComboBox`] with the given [`State`], a list of options, - /// the current selected value, and the message to produce when an option is - /// selected. - /// - /// [`ComboBox`]: struct.ComboBox.html - /// [`State`]: struct.State.html - pub fn new( - state: &'a mut State, - options: impl Into>, - selected: Option, - on_selected: impl Fn(T) -> Message + 'static, - ) -> Self { - let is_open = state.menu.is_open(); - - Self { - menu: &mut state.menu, - on_selected: Box::new(on_selected), - options: options.into(), - selected, - width: Length::Shrink, - text_size: None, - padding: Renderer::DEFAULT_PADDING, - font: Default::default(), - style: Default::default(), - is_open, - } - } - - /// Sets the width of the [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - pub fn width(mut self, width: Length) -> Self { - self.width = width; - self - } - - /// Sets the padding of the [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - pub fn padding(mut self, padding: u16) -> Self { - self.padding = padding; - self - } - - /// Sets the text size of the [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - pub fn text_size(mut self, size: u16) -> Self { - self.text_size = Some(size); - self - } - - /// Sets the font of the [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - pub fn font(mut self, font: Renderer::Font) -> Self { - self.font = font; - self - } - - /// Sets the style of the [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - pub fn style( - mut self, - style: impl Into<::Style>, - ) -> Self { - self.style = style.into(); - self - } -} - -impl<'a, T: 'a, Message, Renderer> Widget - for ComboBox<'a, T, Message, Renderer> -where - T: Clone + ToString + Eq, - [T]: ToOwned>, - Message: 'static, - Renderer: self::Renderer + scrollable::Renderer + 'a, -{ - fn width(&self) -> Length { - Length::Shrink - } - - fn height(&self) -> Length { - Length::Shrink - } - - fn layout( - &self, - renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - use std::f32; - - let limits = limits - .width(self.width) - .height(Length::Shrink) - .pad(f32::from(self.padding)); - - let text_size = self.text_size.unwrap_or(renderer.default_size()); - - let max_width = match self.width { - Length::Shrink => { - let labels = self.options.iter().map(ToString::to_string); - - labels - .map(|label| { - let (width, _) = renderer.measure( - &label, - text_size, - Renderer::Font::default(), - Size::new(f32::INFINITY, f32::INFINITY), - ); - - width.round() as u32 - }) - .max() - .unwrap_or(100) - } - _ => 0, - }; - - let size = { - let intrinsic = Size::new( - max_width as f32 - + f32::from(text_size) - + f32::from(self.padding), - f32::from(text_size), - ); - - limits.resolve(intrinsic).pad(f32::from(self.padding)) - }; - - layout::Node::new(size) - } - - fn hash_layout(&self, state: &mut Hasher) { - use std::hash::Hash as _; - - match self.width { - Length::Shrink => { - self.options - .iter() - .map(ToString::to_string) - .for_each(|label| label.hash(state)); - } - _ => { - self.width.hash(state); - } - } - } - - fn on_event( - &mut self, - event: Event, - layout: Layout<'_>, - cursor_position: Point, - _messages: &mut Vec, - _renderer: &Renderer, - _clipboard: Option<&dyn Clipboard>, - ) { - if !self.is_open { - match event { - Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Left, - )) => { - if layout.bounds().contains(cursor_position) { - let selected = self.selected.as_ref(); - - self.menu.open( - self.options - .iter() - .position(|option| Some(option) == selected), - ); - } - } - _ => {} - } - } - } - - fn draw( - &self, - renderer: &mut Renderer, - _defaults: &Renderer::Defaults, - layout: Layout<'_>, - cursor_position: Point, - ) -> Renderer::Output { - self::Renderer::draw( - renderer, - layout.bounds(), - cursor_position, - self.selected.as_ref().map(ToString::to_string), - self.padding, - self.text_size.unwrap_or(renderer.default_size()), - self.font, - &self.style, - ) - } - - fn overlay( - &mut self, - layout: Layout<'_>, - ) -> Option> { - if self.menu.is_open() { - let bounds = layout.bounds(); - - let mut menu = - Menu::new(&mut self.menu, &self.options, &self.on_selected) - .width(bounds.width.round() as u16) - .padding(self.padding) - .font(self.font) - .style(Renderer::menu_style(&self.style)); - - if let Some(text_size) = self.text_size { - menu = menu.text_size(text_size); - } - - Some(menu.overlay(layout.position(), bounds.height)) - } else { - None - } - } -} - -/// The renderer of a [`ComboBox`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`ComboBox`] in your user interface. -/// -/// [`ComboBox`]: struct.ComboBox.html -/// [renderer]: ../../renderer/index.html -pub trait Renderer: text::Renderer + menu::Renderer { - /// The default padding of a [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - const DEFAULT_PADDING: u16; - - /// The [`ComboBox`] style supported by this renderer. - /// - /// [`ComboBox`]: struct.ComboBox.html - type Style: Default; - - /// Returns the style of the [`Menu`] of the [`ComboBox`]. - /// - /// [`Menu`]: ../../overlay/menu/struct.Menu.html - /// [`ComboBox`]: struct.ComboBox.html - fn menu_style( - style: &::Style, - ) -> ::Style; - - /// Draws a [`ComboBox`]. - /// - /// [`ComboBox`]: struct.ComboBox.html - fn draw( - &mut self, - bounds: Rectangle, - cursor_position: Point, - selected: Option, - padding: u16, - text_size: u16, - font: Self::Font, - style: &::Style, - ) -> Self::Output; -} - -impl<'a, T: 'a, Message, Renderer> Into> - for ComboBox<'a, T, Message, Renderer> -where - T: Clone + ToString + Eq, - [T]: ToOwned>, - Renderer: self::Renderer + 'a, - Message: 'static, -{ - fn into(self) -> Element<'a, Message, Renderer> { - Element::new(self) - } -} diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs new file mode 100644 index 00000000..9f62e550 --- /dev/null +++ b/native/src/widget/pick_list.rs @@ -0,0 +1,320 @@ +//! Display a dropdown list of selectable values. +use crate::{ + layout, mouse, overlay, + overlay::menu::{self, Menu}, + scrollable, text, Clipboard, Element, Event, Hasher, Layout, Length, Point, + Rectangle, Size, Widget, +}; +use std::borrow::Cow; + +/// A widget for selecting a single value from a list of options. +#[allow(missing_debug_implementations)] +pub struct PickList<'a, T, Message, Renderer: self::Renderer> +where + [T]: ToOwned>, +{ + menu: &'a mut menu::State, + on_selected: Box Message>, + options: Cow<'a, [T]>, + selected: Option, + width: Length, + padding: u16, + text_size: Option, + font: Renderer::Font, + style: ::Style, + is_open: bool, +} + +/// The local state of a [`PickList`]. +/// +/// [`PickList`]: struct.PickList.html +#[derive(Debug, Clone, Default)] +pub struct State { + menu: menu::State, +} + +impl<'a, T: 'a, Message, Renderer: self::Renderer> + PickList<'a, T, Message, Renderer> +where + T: ToString, + [T]: ToOwned>, +{ + /// Creates a new [`PickList`] with the given [`State`], a list of options, + /// the current selected value, and the message to produce when an option is + /// selected. + /// + /// [`PickList`]: struct.PickList.html + /// [`State`]: struct.State.html + pub fn new( + state: &'a mut State, + options: impl Into>, + selected: Option, + on_selected: impl Fn(T) -> Message + 'static, + ) -> Self { + let is_open = state.menu.is_open(); + + Self { + menu: &mut state.menu, + on_selected: Box::new(on_selected), + options: options.into(), + selected, + width: Length::Shrink, + text_size: None, + padding: Renderer::DEFAULT_PADDING, + font: Default::default(), + style: Default::default(), + is_open, + } + } + + /// Sets the width of the [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + pub fn width(mut self, width: Length) -> Self { + self.width = width; + self + } + + /// Sets the padding of the [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + pub fn padding(mut self, padding: u16) -> Self { + self.padding = padding; + self + } + + /// Sets the text size of the [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + pub fn text_size(mut self, size: u16) -> Self { + self.text_size = Some(size); + self + } + + /// Sets the font of the [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + pub fn font(mut self, font: Renderer::Font) -> Self { + self.font = font; + self + } + + /// Sets the style of the [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + pub fn style( + mut self, + style: impl Into<::Style>, + ) -> Self { + self.style = style.into(); + self + } +} + +impl<'a, T: 'a, Message, Renderer> Widget + for PickList<'a, T, Message, Renderer> +where + T: Clone + ToString + Eq, + [T]: ToOwned>, + Message: 'static, + Renderer: self::Renderer + scrollable::Renderer + 'a, +{ + fn width(&self) -> Length { + Length::Shrink + } + + fn height(&self) -> Length { + Length::Shrink + } + + fn layout( + &self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + use std::f32; + + let limits = limits + .width(self.width) + .height(Length::Shrink) + .pad(f32::from(self.padding)); + + let text_size = self.text_size.unwrap_or(renderer.default_size()); + + let max_width = match self.width { + Length::Shrink => { + let labels = self.options.iter().map(ToString::to_string); + + labels + .map(|label| { + let (width, _) = renderer.measure( + &label, + text_size, + Renderer::Font::default(), + Size::new(f32::INFINITY, f32::INFINITY), + ); + + width.round() as u32 + }) + .max() + .unwrap_or(100) + } + _ => 0, + }; + + let size = { + let intrinsic = Size::new( + max_width as f32 + + f32::from(text_size) + + f32::from(self.padding), + f32::from(text_size), + ); + + limits.resolve(intrinsic).pad(f32::from(self.padding)) + }; + + layout::Node::new(size) + } + + fn hash_layout(&self, state: &mut Hasher) { + use std::hash::Hash as _; + + match self.width { + Length::Shrink => { + self.options + .iter() + .map(ToString::to_string) + .for_each(|label| label.hash(state)); + } + _ => { + self.width.hash(state); + } + } + } + + fn on_event( + &mut self, + event: Event, + layout: Layout<'_>, + cursor_position: Point, + _messages: &mut Vec, + _renderer: &Renderer, + _clipboard: Option<&dyn Clipboard>, + ) { + if !self.is_open { + match event { + Event::Mouse(mouse::Event::ButtonPressed( + mouse::Button::Left, + )) => { + if layout.bounds().contains(cursor_position) { + let selected = self.selected.as_ref(); + + self.menu.open( + self.options + .iter() + .position(|option| Some(option) == selected), + ); + } + } + _ => {} + } + } + } + + fn draw( + &self, + renderer: &mut Renderer, + _defaults: &Renderer::Defaults, + layout: Layout<'_>, + cursor_position: Point, + ) -> Renderer::Output { + self::Renderer::draw( + renderer, + layout.bounds(), + cursor_position, + self.selected.as_ref().map(ToString::to_string), + self.padding, + self.text_size.unwrap_or(renderer.default_size()), + self.font, + &self.style, + ) + } + + fn overlay( + &mut self, + layout: Layout<'_>, + ) -> Option> { + if self.menu.is_open() { + let bounds = layout.bounds(); + + let mut menu = + Menu::new(&mut self.menu, &self.options, &self.on_selected) + .width(bounds.width.round() as u16) + .padding(self.padding) + .font(self.font) + .style(Renderer::menu_style(&self.style)); + + if let Some(text_size) = self.text_size { + menu = menu.text_size(text_size); + } + + Some(menu.overlay(layout.position(), bounds.height)) + } else { + None + } + } +} + +/// The renderer of a [`PickList`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`PickList`] in your user interface. +/// +/// [`PickList`]: struct.PickList.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer: text::Renderer + menu::Renderer { + /// The default padding of a [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + const DEFAULT_PADDING: u16; + + /// The [`PickList`] style supported by this renderer. + /// + /// [`PickList`]: struct.PickList.html + type Style: Default; + + /// Returns the style of the [`Menu`] of the [`PickList`]. + /// + /// [`Menu`]: ../../overlay/menu/struct.Menu.html + /// [`PickList`]: struct.PickList.html + fn menu_style( + style: &::Style, + ) -> ::Style; + + /// Draws a [`PickList`]. + /// + /// [`PickList`]: struct.PickList.html + fn draw( + &mut self, + bounds: Rectangle, + cursor_position: Point, + selected: Option, + padding: u16, + text_size: u16, + font: Self::Font, + style: &::Style, + ) -> Self::Output; +} + +impl<'a, T: 'a, Message, Renderer> Into> + for PickList<'a, T, Message, Renderer> +where + T: Clone + ToString + Eq, + [T]: ToOwned>, + Renderer: self::Renderer + 'a, + Message: 'static, +{ + fn into(self) -> Element<'a, Message, Renderer> { + Element::new(self) + } +} -- cgit