diff options
Diffstat (limited to 'native/src/overlay/menu.rs')
-rw-r--r-- | native/src/overlay/menu.rs | 116 |
1 files changed, 63 insertions, 53 deletions
diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs index c2df468e..f62dcb46 100644 --- a/native/src/overlay/menu.rs +++ b/native/src/overlay/menu.rs @@ -1,8 +1,15 @@ //! Build and show dropdown menus. +use crate::container; +use crate::event::{self, Event}; +use crate::layout; +use crate::mouse; +use crate::overlay; +use crate::scrollable; +use crate::text; +use crate::touch; use crate::{ - container, layout, mouse, overlay, scrollable, text, Clipboard, Container, - Element, Event, Hasher, Layout, Length, Point, Rectangle, Scrollable, Size, - Vector, Widget, + Clipboard, Container, Element, Hasher, Layout, Length, Padding, Point, + Rectangle, Scrollable, Size, Vector, Widget, }; /// A list of selectable options. @@ -13,7 +20,7 @@ pub struct Menu<'a, T, Renderer: self::Renderer> { hovered_option: &'a mut Option<usize>, last_selection: &'a mut Option<T>, width: u16, - padding: u16, + padding: Padding, text_size: Option<u16>, font: Renderer::Font, style: <Renderer as self::Renderer>::Style, @@ -26,9 +33,6 @@ where { /// Creates a new [`Menu`] with the given [`State`], a list of options, and /// the message to produced when an option is selected. - /// - /// [`Menu`]: struct.Menu.html - /// [`State`]: struct.State.html pub fn new( state: &'a mut State, options: &'a [T], @@ -41,7 +45,7 @@ where hovered_option, last_selection, width: 0, - padding: 0, + padding: Padding::ZERO, text_size: None, font: Default::default(), style: Default::default(), @@ -49,40 +53,30 @@ where } /// Sets the width of the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html pub fn width(mut self, width: u16) -> Self { self.width = width; self } - /// Sets the padding of the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html - pub fn padding(mut self, padding: u16) -> Self { - self.padding = padding; + /// Sets the [`Padding`] of the [`Menu`]. + pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self { + self.padding = padding.into(); self } /// Sets the text size of the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html pub fn text_size(mut self, text_size: u16) -> Self { self.text_size = Some(text_size); self } /// Sets the font of the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html pub fn font(mut self, font: Renderer::Font) -> Self { self.font = font; self } /// Sets the style of the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html pub fn style( mut self, style: impl Into<<Renderer as self::Renderer>::Style>, @@ -97,8 +91,6 @@ where /// The `target_height` will be used to display the menu either on top /// of the target or under it, depending on the screen position and the /// dimensions of the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html pub fn overlay<Message: 'a>( self, position: Point, @@ -112,8 +104,6 @@ where } /// The local state of a [`Menu`]. -/// -/// [`Menu`]: struct.Menu.html #[derive(Debug, Clone, Default)] pub struct State { scrollable: scrollable::State, @@ -121,9 +111,6 @@ pub struct State { impl State { /// Creates a new [`State`] for a [`Menu`]. - /// - /// [`State`]: struct.State.html - /// [`Menu`]: struct.Menu.html pub fn new() -> Self { Self::default() } @@ -232,18 +219,18 @@ where event: Event, layout: Layout<'_>, cursor_position: Point, - messages: &mut Vec<Message>, renderer: &Renderer, - clipboard: Option<&dyn Clipboard>, - ) { + clipboard: &mut dyn Clipboard, + messages: &mut Vec<Message>, + ) -> event::Status { self.container.on_event( event.clone(), layout, cursor_position, - messages, renderer, clipboard, - ); + messages, + ) } fn draw( @@ -253,9 +240,13 @@ where layout: Layout<'_>, cursor_position: Point, ) -> Renderer::Output { - let primitives = - self.container - .draw(renderer, defaults, layout, cursor_position); + let primitives = self.container.draw( + renderer, + defaults, + layout, + cursor_position, + &layout.bounds(), + ); renderer.decorate( layout.bounds(), @@ -270,7 +261,7 @@ struct List<'a, T, Renderer: self::Renderer> { options: &'a [T], hovered_option: &'a mut Option<usize>, last_selection: &'a mut Option<T>, - padding: u16, + padding: Padding, text_size: Option<u16>, font: Renderer::Font, style: <Renderer as self::Renderer>::Style, @@ -303,7 +294,7 @@ where let size = { let intrinsic = Size::new( 0.0, - f32::from(text_size + self.padding * 2) + f32::from(text_size + self.padding.vertical()) * self.options.len() as f32, ); @@ -329,10 +320,10 @@ where event: Event, layout: Layout<'_>, cursor_position: Point, - _messages: &mut Vec<Message>, renderer: &Renderer, - _clipboard: Option<&dyn Clipboard>, - ) { + _clipboard: &mut dyn Clipboard, + _messages: &mut Vec<Message>, + ) -> event::Status { match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { let bounds = layout.bounds(); @@ -347,19 +338,42 @@ where } Event::Mouse(mouse::Event::CursorMoved { .. }) => { let bounds = layout.bounds(); - let text_size = - self.text_size.unwrap_or(renderer.default_size()); if bounds.contains(cursor_position) { + let text_size = + self.text_size.unwrap_or(renderer.default_size()); + *self.hovered_option = Some( ((cursor_position.y - bounds.y) - / f32::from(text_size + self.padding * 2)) + / f32::from(text_size + self.padding.vertical())) as usize, ); } } + Event::Touch(touch::Event::FingerPressed { .. }) => { + let bounds = layout.bounds(); + + if bounds.contains(cursor_position) { + let text_size = + self.text_size.unwrap_or(renderer.default_size()); + + *self.hovered_option = Some( + ((cursor_position.y - bounds.y) + / f32::from(text_size + self.padding.vertical())) + as usize, + ); + + if let Some(index) = *self.hovered_option { + if let Some(option) = self.options.get(index) { + *self.last_selection = Some(option.clone()); + } + } + } + } _ => {} } + + event::Status::Ignored } fn draw( @@ -368,11 +382,13 @@ where _defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + viewport: &Rectangle, ) -> Renderer::Output { self::Renderer::draw( renderer, layout.bounds(), cursor_position, + viewport, self.options, *self.hovered_option, self.padding, @@ -388,21 +404,16 @@ where /// Your [renderer] will need to implement this trait before being /// able to use a [`Menu`] in your user interface. /// -/// [`Menu`]: struct.Menu.html -/// [renderer]: ../../renderer/index.html +/// [renderer]: crate::renderer pub trait Renderer: scrollable::Renderer + container::Renderer + text::Renderer { /// The [`Menu`] style supported by this renderer. - /// - /// [`Menu`]: struct.Menu.html type Style: Default + Clone; /// Decorates a the list of options of a [`Menu`]. /// /// This method can be used to draw a background for the [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html fn decorate( &mut self, bounds: Rectangle, @@ -412,15 +423,14 @@ pub trait Renderer: ) -> Self::Output; /// Draws the list of options of a [`Menu`]. - /// - /// [`Menu`]: struct.Menu.html fn draw<T: ToString>( &mut self, bounds: Rectangle, cursor_position: Point, + viewport: &Rectangle, options: &[T], hovered_option: Option<usize>, - padding: u16, + padding: Padding, text_size: u16, font: Self::Font, style: &<Self as Renderer>::Style, |