diff options
Diffstat (limited to 'native/src/widget/radio.rs')
-rw-r--r-- | native/src/widget/radio.rs | 122 |
1 files changed, 84 insertions, 38 deletions
diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 46983db3..3a1dd386 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -1,9 +1,13 @@ //! Create choices using radio buttons. +use crate::event::{self, Event}; +use crate::layout; +use crate::mouse; +use crate::row; +use crate::text; +use crate::touch::{self, Touch}; use crate::{ - input::{mouse, touch, ButtonState, Touch}, - layout, row, text, Align, Clipboard, Element, Event, Font, Hasher, - HorizontalAlignment, Layout, Length, Point, Rectangle, Row, Text, - VerticalAlignment, Widget, + Align, Clipboard, Element, Hasher, HorizontalAlignment, Layout, Length, + Point, Rectangle, Row, Text, VerticalAlignment, Widget, }; use std::hash::Hash; @@ -35,14 +39,22 @@ use std::hash::Hash; /// ///  #[allow(missing_debug_implementations)] -pub struct Radio<Message, Renderer: self::Renderer> { +pub struct Radio<Message, Renderer: self::Renderer + text::Renderer> { is_selected: bool, on_click: Message, label: String, + width: Length, + size: u16, + spacing: u16, + text_size: Option<u16>, style: Renderer::Style, } -impl<Message, Renderer: self::Renderer> Radio<Message, Renderer> { +impl<Message, Renderer: self::Renderer + text::Renderer> + Radio<Message, Renderer> +where + Message: Clone, +{ /// Creates a new [`Radio`] button. /// /// It expects: @@ -51,9 +63,12 @@ impl<Message, Renderer: self::Renderer> Radio<Message, Renderer> { /// * the current selected value /// * a function that will be called when the [`Radio`] is selected. It /// receives the value of the radio and must produce a `Message`. - /// - /// [`Radio`]: struct.Radio.html - pub fn new<F, V>(value: V, label: &str, selected: Option<V>, f: F) -> Self + pub fn new<F, V>( + value: V, + label: impl Into<String>, + selected: Option<V>, + f: F, + ) -> Self where V: Eq + Copy, F: 'static + Fn(V) -> Message, @@ -61,14 +76,40 @@ impl<Message, Renderer: self::Renderer> Radio<Message, Renderer> { Radio { is_selected: Some(value) == selected, on_click: f(value), - label: String::from(label), + label: label.into(), + width: Length::Shrink, + size: <Renderer as self::Renderer>::DEFAULT_SIZE, + spacing: Renderer::DEFAULT_SPACING, //15 + text_size: None, style: Renderer::Style::default(), } } + /// Sets the size of the [`Radio`] button. + pub fn size(mut self, size: u16) -> Self { + self.size = size; + self + } + + /// Sets the width of the [`Radio`] button. + pub fn width(mut self, width: Length) -> Self { + self.width = width; + self + } + + /// Sets the spacing between the [`Radio`] button and the text. + pub fn spacing(mut self, spacing: u16) -> Self { + self.spacing = spacing; + self + } + + /// Sets the text size of the [`Radio`] button. + pub fn text_size(mut self, text_size: u16) -> Self { + self.text_size = Some(text_size); + self + } + /// Sets the style of the [`Radio`] button. - /// - /// [`Radio`]: struct.Radio.html pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self { self.style = style.into(); self @@ -77,11 +118,11 @@ impl<Message, Renderer: self::Renderer> Radio<Message, Renderer> { impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message, Renderer> where - Renderer: self::Renderer + text::Renderer + row::Renderer, Message: Clone, + Renderer: self::Renderer + text::Renderer + row::Renderer, { fn width(&self) -> Length { - Length::Fill + self.width } fn height(&self) -> Length { @@ -93,18 +134,20 @@ where renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let size = self::Renderer::default_size(renderer); - Row::<(), Renderer>::new() - .width(Length::Fill) - .spacing(15) + .width(self.width) + .spacing(self.spacing) .align_items(Align::Center) .push( Row::new() - .width(Length::Units(size as u16)) - .height(Length::Units(size as u16)), + .width(Length::Units(self.size)) + .height(Length::Units(self.size)), + ) + .push( + Text::new(&self.label) + .width(self.width) + .size(self.text_size.unwrap_or(renderer.default_size())), ) - .push(Text::new(&self.label)) .layout(renderer, limits) } @@ -116,22 +159,23 @@ where messages: &mut Vec<Message>, _renderer: &Renderer, _clipboard: Option<&dyn Clipboard>, - ) { + ) -> event::Status { match event { - Event::Mouse(mouse::Event::Input { - button: mouse::Button::Left, - state: ButtonState::Pressed, - }) + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(Touch { phase: touch::Phase::Started, .. }) => { if layout.bounds().contains(cursor_position) { messages.push(self.on_click.clone()); + + return event::Status::Captured; } } _ => {} } + + event::Status::Ignored } fn draw( @@ -140,6 +184,7 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + _viewport: &Rectangle, ) -> Renderer::Output { let bounds = layout.bounds(); let mut children = layout.children(); @@ -153,8 +198,8 @@ where defaults, label_layout.bounds(), &self.label, - <Renderer as text::Renderer>::DEFAULT_SIZE, - Font::Default, + self.text_size.unwrap_or(renderer.default_size()), + Default::default(), None, HorizontalAlignment::Left, VerticalAlignment::Center, @@ -173,6 +218,9 @@ where } fn hash_layout(&self, state: &mut Hasher) { + struct Marker; + std::any::TypeId::of::<Marker>().hash(state); + self.label.hash(state); } } @@ -182,16 +230,16 @@ where /// Your [renderer] will need to implement this trait before being /// able to use a [`Radio`] button in your user interface. /// -/// [`Radio`]: struct.Radio.html -/// [renderer]: ../../renderer/index.html +/// [renderer]: crate::renderer pub trait Renderer: crate::Renderer { /// The style supported by this renderer. type Style: Default; - /// Returns the default size of a [`Radio`] button. - /// - /// [`Radio`]: struct.Radio.html - fn default_size(&self) -> u32; + /// The default size of a [`Radio`] button. + const DEFAULT_SIZE: u16; + + /// The default spacing of a [`Radio`] button. + const DEFAULT_SPACING: u16; /// Draws a [`Radio`] button. /// @@ -200,8 +248,6 @@ pub trait Renderer: crate::Renderer { /// * whether the [`Radio`] is selected or not /// * whether the mouse is over the [`Radio`] or not /// * the drawn label of the [`Radio`] - /// - /// [`Radio`]: struct.Radio.html fn draw( &mut self, bounds: Rectangle, @@ -215,8 +261,8 @@ pub trait Renderer: crate::Renderer { impl<'a, Message, Renderer> From<Radio<Message, Renderer>> for Element<'a, Message, Renderer> where - Renderer: 'static + self::Renderer + row::Renderer + text::Renderer, - Message: 'static + Clone, + Message: 'a + Clone, + Renderer: 'a + self::Renderer + row::Renderer + text::Renderer, { fn from(radio: Radio<Message, Renderer>) -> Element<'a, Message, Renderer> { Element::new(radio) |