From e83260ff10e37db8df0d9af1da0fa48b7442d91e Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Sat, 17 Feb 2024 17:48:38 +0100 Subject: [PATCH 1/4] init --- .gitignore | 1 + .vscode/settings.json | 0 Cargo.toml | 3 + examples/context_menu/Cargo.toml | 3 +- examples/drop_down/Cargo.toml | 12 + examples/drop_down/src/main.rs | 101 ++++++++ src/core/alignment.rs | 26 ++ src/core/mod.rs | 6 + src/core/offset.rs | 46 ++++ src/lib.rs | 6 + src/native/drop_down.rs | 405 +++++++++++++++++++++++++++++++ src/native/mod.rs | 7 + 12 files changed, 614 insertions(+), 2 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 examples/drop_down/Cargo.toml create mode 100644 examples/drop_down/src/main.rs create mode 100644 src/core/alignment.rs create mode 100644 src/core/offset.rs create mode 100644 src/native/drop_down.rs diff --git a/.gitignore b/.gitignore index b8775058..f401a212 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ pkg/ .idea *.lock .DS_Store +.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e69de29b..00000000 diff --git a/Cargo.toml b/Cargo.toml index 7251184d..7318e4f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ spinner = [] context_menu = [] segmented_button = [] slide_bar = [] +drop_down = [] default = [ "badge", @@ -60,6 +61,7 @@ default = [ "spinner", "cupertino", "segmented_button", + "drop_down", #"menu", ] @@ -108,6 +110,7 @@ members = [ "examples/cupertino/cupertino_switch", "examples/WidgetIDReturn", "examples/segmented_button", + "examples/drop_down", #"examples/menu", ] diff --git a/examples/context_menu/Cargo.toml b/examples/context_menu/Cargo.toml index f8347d9b..e77ce25e 100644 --- a/examples/context_menu/Cargo.toml +++ b/examples/context_menu/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "context_menu" version = "0.1.0" -authors = ["wiiznokes "] +authors = ["wiiznokes "] edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] iced_aw = { workspace = true, features = [ diff --git a/examples/drop_down/Cargo.toml b/examples/drop_down/Cargo.toml new file mode 100644 index 00000000..5f27a79d --- /dev/null +++ b/examples/drop_down/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "drop_down" +version = "0.1.0" +authors = ["wiiznokes "] +edition = "2021" + + +[dependencies] +iced_aw = { workspace = true, features = [ + "drop_down", +] } +iced.workspace = true \ No newline at end of file diff --git a/examples/drop_down/src/main.rs b/examples/drop_down/src/main.rs new file mode 100644 index 00000000..eff430fe --- /dev/null +++ b/examples/drop_down/src/main.rs @@ -0,0 +1,101 @@ +use std::fmt::Display; + +use iced::{ + widget::{Button, Column, Row, Text}, Element, Length, Sandbox, Settings +}; + +use iced_aw::{drop_down, DropDown}; + +fn main() -> iced::Result { + DropDownExample::run(Settings::default()) +} + +#[derive(Clone, Debug, Default)] +enum Choice { + #[default] + Choice1, + Choice2, + Choice3, + Choice4, +} + +const CHOICES: [Choice; 4] = [ + Choice::Choice1, + Choice::Choice2, + Choice::Choice3, + Choice::Choice4, +]; + +#[derive(Clone, Debug)] +enum Message { + Select(Choice), + Dismiss, + Expand, +} + +#[derive(Default)] +struct DropDownExample { + selected: Choice, + expanded: bool, +} + +impl Sandbox for DropDownExample { + type Message = Message; + + fn new() -> Self { + Self::default() + } + + fn title(&self) -> String { + String::from("ContextMenu example") + } + + fn update(&mut self, message: Self::Message) { + match message { + Message::Select(choice) => { + self.selected = choice; + self.expanded = false; + }, + Message::Dismiss => self.expanded = false, + Message::Expand => self.expanded = !self.expanded, + } + } + + fn view(&self) -> Element<'_, Self::Message> { + let underlay = Row::new() + .push(Text::new(format!("Selected: {}", self.selected))) + .push(Button::new(Text::new("expand")).on_press(Message::Expand)); + + let overlay = Column::with_children(CHOICES.map(|choice| { + Row::new() + .push(Text::new(choice.to_string())) + .push(Button::new(Text::new("choose")).on_press(Message::Select(choice))) + .into() + })); + + let drop_down = DropDown::new(underlay, overlay, self.expanded) + .width(Length::Fill) + .on_dismiss(Message::Dismiss) + .alignment(drop_down::Alignment::Bottom); + + + Column::new() + .padding(20) + .width(Length::Fill) + .height(Length::Fill) + .align_items(iced::Alignment::Center) + .push(drop_down) + .into() + } +} + +impl Display for Choice { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Choice::Choice1 => write!(f, "1"), + Choice::Choice2 => write!(f, "2"), + Choice::Choice3 => write!(f, "3"), + Choice::Choice4 => write!(f, "4"), + } + } +} diff --git a/src/core/alignment.rs b/src/core/alignment.rs new file mode 100644 index 00000000..044eba1a --- /dev/null +++ b/src/core/alignment.rs @@ -0,0 +1,26 @@ +//! Alignment enum, similar to an anchor + +/// ```text +/// +-----------+-----------+-----------+ +/// | TopStart | Top | TopEnd | +/// +-----------+-----------+-----------+ +/// | Start | | End | +/// +-----------+-----------+-----------+ +/// |BottomStart| Bottom | BottomEnd | +/// +-----------+-----------+-----------+ +/// ``` +#[allow(missing_docs)] +#[derive(Debug, Clone, PartialEq)] +pub enum Alignment { + TopStart, + Top, + TopEnd, + + End, + + BottomEnd, + Bottom, + BottomStart, + + Start, +} diff --git a/src/core/mod.rs b/src/core/mod.rs index a82d022b..a4d54d3b 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -16,3 +16,9 @@ pub mod renderer; #[cfg(feature = "time_picker")] pub mod time; + +#[cfg(feature = "drop_down")] +pub mod offset; + +#[cfg(feature = "drop_down")] +pub mod alignment; \ No newline at end of file diff --git a/src/core/offset.rs b/src/core/offset.rs new file mode 100644 index 00000000..eafee04b --- /dev/null +++ b/src/core/offset.rs @@ -0,0 +1,46 @@ +//! Offset struct + +use iced::Point; + +/// Represents an offset in a two-dimensional space. +#[derive(Copy, Clone, Debug)] +pub struct Offset { + /// Offset on the x-axis + pub x: f32, + /// Offset on the y-axis + pub y: f32, +} + +impl Offset { + /// Construct a new [`Offset`] + pub fn new(x: f32, y: f32) -> Self { + Offset { x, y } + } +} + +impl From for Offset { + fn from(float: f32) -> Self { + Self { x: float, y: float } + } +} + +impl From<[f32; 2]> for Offset { + fn from(array: [f32; 2]) -> Self { + Self { + x: array[0], + y: array[1], + } + } +} + +impl From for Point { + fn from(offset: Offset) -> Self { + Self::new(offset.x, offset.y) + } +} + +impl From<&Offset> for Point { + fn from(offset: &Offset) -> Self { + Self::new(offset.x, offset.y) + } +} diff --git a/src/lib.rs b/src/lib.rs index b8a2982b..21ea6b87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,6 +167,12 @@ mod platform { pub use { crate::native::context_menu, crate::style::ContextMenuStyle, context_menu::ContextMenu, }; + + #[doc(no_inline)] + #[cfg(feature = "drop_down")] + pub use { + crate::native::drop_down, drop_down::DropDown, + }; } #[doc(no_inline)] diff --git a/src/native/drop_down.rs b/src/native/drop_down.rs new file mode 100644 index 00000000..4679be20 --- /dev/null +++ b/src/native/drop_down.rs @@ -0,0 +1,405 @@ +#![allow(missing_docs)] + +use iced::{ + self, + advanced::{ + layout::{Limits, Node}, + overlay, renderer, + widget::{Operation, Tree}, + Clipboard, Layout, Shell, Widget, + }, + event, + keyboard::{self, key::Named}, + mouse::{self, Cursor}, + touch, Element, Event, Length, Point, Rectangle, Size, Vector, +}; + +pub use crate::core::{alignment::Alignment, offset::Offset}; + +/// Drop down menu +pub struct DropDown<'a, Message, Theme = iced::Theme, Renderer = iced::Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + underlay: Element<'a, Message, Theme, Renderer>, + overlay: Element<'a, Message, Theme, Renderer>, + on_dismiss: Option, + width: Option, + height: Length, + alignment: Alignment, + offset: Offset, + expanded: bool, +} + +impl<'a, Message, Theme, Renderer> DropDown<'a, Message, Theme, Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + /// Create a new DropDown + pub fn new(underlay: U, overlay: B, expanded: bool) -> Self + where + U: Into>, + B: Into>, + { + DropDown { + underlay: underlay.into(), + overlay: overlay.into(), + expanded, + on_dismiss: None, + width: None, + height: Length::Shrink, + alignment: Alignment::Bottom, + offset: Offset::from(5.0), + } + } + + /// The width of the overlay + pub fn width(mut self, width: impl Into) -> Self { + self.width = Some(width.into()); + self + } + + /// The height of the overlay + pub fn height(mut self, height: impl Into) -> Self { + self.height = height.into(); + self + } + + /// The alignment of the overlay relative to the underlay + pub fn alignment(mut self, alignment: impl Into) -> Self { + self.alignment = alignment.into(); + self + } + + /// The offset of the overlay + pub fn offset(mut self, offset: impl Into) -> Self { + self.offset = offset.into(); + self + } + + /// Send a message when a click occur outside of the overlay when expanded + pub fn on_dismiss(mut self, message: Message) -> Self { + self.on_dismiss = Some(message); + self + } +} + + +impl<'a, Message, Theme, Renderer> Widget + for DropDown<'a, Message, Theme, Renderer> +where + Message: 'a + Clone, + Renderer: 'a + renderer::Renderer, +{ + fn size(&self) -> Size { + self.underlay.as_widget().size() + } + + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay + .as_widget() + .layout(&mut tree.children[0], renderer, limits) + } + + fn draw( + &self, + state: &Tree, + renderer: &mut Renderer, + theme: &Theme, + style: &renderer::Style, + layout: Layout<'_>, + cursor: Cursor, + viewport: &Rectangle, + ) { + self.underlay.as_widget().draw( + &state.children[0], + renderer, + theme, + style, + layout, + cursor, + viewport, + ); + } + + fn children(&self) -> Vec { + vec![Tree::new(&self.underlay), Tree::new(&self.overlay)] + } + + fn diff(&self, tree: &mut Tree) { + tree.diff_children(&[&self.underlay, &self.overlay]); + } + + fn operate<'b>( + &'b self, + state: &'b mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn Operation, + ) { + self.underlay + .as_widget() + .operate(&mut state.children[0], layout, renderer, operation); + } + + fn on_event( + &mut self, + state: &mut Tree, + event: Event, + layout: Layout<'_>, + cursor: Cursor, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, Message>, + viewport: &Rectangle, + ) -> event::Status { + self.underlay.as_widget_mut().on_event( + &mut state.children[0], + event, + layout, + cursor, + renderer, + clipboard, + shell, + viewport, + ) + } + + fn mouse_interaction( + &self, + state: &Tree, + layout: Layout<'_>, + cursor: Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + self.underlay.as_widget().mouse_interaction( + &state.children[0], + layout, + cursor, + viewport, + renderer, + ) + } + + fn overlay<'b>( + &'b mut self, + state: &'b mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + translation: Vector, + ) -> Option> { + if !self.expanded { + return self.underlay.as_widget_mut().overlay( + &mut state.children[0], + layout, + renderer, + translation, + ); + } + + Some(overlay::Element::new(Box::new(DropDownOverlay::new( + &mut state.children[1], + &mut self.overlay, + &self.on_dismiss, + &self.width, + &self.height, + &self.alignment, + &self.offset, + layout.bounds(), + layout.position(), + )))) + } +} + +impl<'a, Message, Theme: 'a, Renderer> From> + for Element<'a, Message, Theme, Renderer> +where + Message: 'a + Clone, + Renderer: 'a + renderer::Renderer, +{ + fn from(drop_down: DropDown<'a, Message, Theme, Renderer>) -> Self { + Element::new(drop_down) + } +} + +struct DropDownOverlay<'a, 'b, Message, Theme = iced::Theme, Renderer = iced::Renderer> +where + Message: Clone, +{ + state: &'b mut Tree, + element: &'b mut Element<'a, Message, Theme, Renderer>, + on_dismiss: &'b Option, + width: &'b Option, + height: &'b Length, + alignment: &'b Alignment, + offset: &'b Offset, + underlay_bounds: Rectangle, + position: Point, +} + +impl<'a, 'b, Message, Theme, Renderer> DropDownOverlay<'a, 'b, Message, Theme, Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + fn new( + state: &'b mut Tree, + element: &'b mut Element<'a, Message, Theme, Renderer>, + on_dismiss: &'b Option, + width: &'b Option, + height: &'b Length, + alignment: &'b Alignment, + offset: &'b Offset, + underlay_bounds: Rectangle, + position: Point, + ) -> Self { + DropDownOverlay { + state, + element, + on_dismiss, + underlay_bounds, + width, + alignment, + offset, + height, + position, + } + } +} + +impl<'a, 'b, Message, Theme, Renderer> overlay::Overlay + for DropDownOverlay<'a, 'b, Message, Theme, Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + fn layout(&mut self, renderer: &Renderer, bounds: Size) -> Node { + let limits = Limits::new(Size::ZERO, bounds) + .width( + self.width + .unwrap_or(Length::Fixed(self.underlay_bounds.width)), + ) + .height(*self.height); + + let mut node = self + .element + .as_widget() + .layout(self.state, renderer, &limits); + + let previous_position = self.position; + + let new_position = match self.alignment { + Alignment::TopStart => Point::new( + previous_position.x - node.bounds().width - self.offset.x, + previous_position.y - node.bounds().height + self.underlay_bounds.height + - self.offset.y, + ), + Alignment::Top => Point::new( + previous_position.x + self.underlay_bounds.width / 2.0 - node.bounds().width / 2.0, + previous_position.y - node.bounds().height - self.offset.y, + ), + Alignment::TopEnd => Point::new( + previous_position.x + self.underlay_bounds.width + self.offset.x, + previous_position.y - node.bounds().height + self.underlay_bounds.height + - self.offset.y, + ), + Alignment::End => Point::new( + previous_position.x + self.underlay_bounds.width + self.offset.x, + previous_position.y + self.underlay_bounds.height / 2.0 + - node.bounds().height / 2.0, + ), + Alignment::BottomEnd => Point::new( + previous_position.x + self.underlay_bounds.width + self.offset.x, + previous_position.y + self.offset.y, + ), + Alignment::Bottom => Point::new( + previous_position.x + self.underlay_bounds.width / 2.0 - node.bounds().width / 2.0, + previous_position.y + self.underlay_bounds.height + self.offset.y, + ), + Alignment::BottomStart => Point::new( + previous_position.x - node.bounds().width - self.offset.x, + previous_position.y + self.offset.y, + ), + Alignment::Start => Point::new( + previous_position.x - node.bounds().width - self.offset.x, + previous_position.y + self.underlay_bounds.height / 2.0 + - node.bounds().height / 2.0, + ), + }; + + node.move_to_mut(new_position); + + node + } + + fn draw( + &self, + renderer: &mut Renderer, + theme: &Theme, + style: &renderer::Style, + layout: Layout<'_>, + cursor: Cursor, + ) { + let bounds = layout.bounds(); + self.element + .as_widget() + .draw(self.state, renderer, theme, style, layout, cursor, &bounds); + } + + fn on_event( + &mut self, + event: Event, + layout: Layout<'_>, + cursor: Cursor, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell, + ) -> event::Status { + if let Some(on_dismiss) = self.on_dismiss { + match &event { + Event::Keyboard(keyboard::Event::KeyPressed { key, .. }) => { + if key == &keyboard::Key::Named(Named::Escape) { + shell.publish(on_dismiss.clone()); + } + } + + Event::Mouse(mouse::Event::ButtonPressed( + mouse::Button::Left | mouse::Button::Right, + )) + | Event::Touch(touch::Event::FingerPressed { .. }) => { + if !cursor.is_over(layout.bounds()) && !cursor.is_over(self.underlay_bounds) { + shell.publish(on_dismiss.clone()); + } + } + + _ => {} + } + } + + self.element.as_widget_mut().on_event( + self.state, + event, + layout, + cursor, + renderer, + clipboard, + shell, + &layout.bounds(), + ) + } + + fn mouse_interaction( + &self, + layout: Layout<'_>, + cursor: Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + self.element + .as_widget() + .mouse_interaction(self.state, layout, cursor, viewport, renderer) + } +} diff --git a/src/native/mod.rs b/src/native/mod.rs index bbb4f57c..3d48b225 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -143,3 +143,10 @@ pub type SegmentedButton<'a, Message, Theme, Renderer> = pub mod slide_bar; #[cfg(feature = "slide_bar")] pub use slide_bar::SlideBar; + +#[cfg(feature = "drop_down")] +pub mod drop_down; +#[cfg(feature = "drop_down")] +/// A drop down menu +pub type DropDown<'a, Overlay, Message, Renderer> = + drop_down::DropDown<'a, Overlay, Message, Renderer>; \ No newline at end of file From b6c8813322cdc6011fa86f1288636d9d63e4beb2 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Sat, 17 Feb 2024 17:53:08 +0100 Subject: [PATCH 2/4] add in rdm --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 530e7fba..1d1dbf19 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,13 @@ Please take a look into our examples on how to use slidebars. Enable this widget with the feature `slide_bar`. +### Context Menu + +See the example [here](./examples/context_menu/src/main.rs) + +### Drop Down Menu + +See the example [here](./examples/drop_down/src/main.rs) ## Quickstart features From 64cef865a442ab963321d7562d51ac88eae65530 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Sat, 17 Feb 2024 17:55:23 +0100 Subject: [PATCH 3/4] fmt --- examples/drop_down/src/main.rs | 6 +++--- src/core/mod.rs | 2 +- src/lib.rs | 4 +--- src/native/drop_down.rs | 1 - src/native/mod.rs | 2 +- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/drop_down/src/main.rs b/examples/drop_down/src/main.rs index eff430fe..fca3b65e 100644 --- a/examples/drop_down/src/main.rs +++ b/examples/drop_down/src/main.rs @@ -1,7 +1,8 @@ use std::fmt::Display; use iced::{ - widget::{Button, Column, Row, Text}, Element, Length, Sandbox, Settings + widget::{Button, Column, Row, Text}, + Element, Length, Sandbox, Settings, }; use iced_aw::{drop_down, DropDown}; @@ -55,7 +56,7 @@ impl Sandbox for DropDownExample { Message::Select(choice) => { self.selected = choice; self.expanded = false; - }, + } Message::Dismiss => self.expanded = false, Message::Expand => self.expanded = !self.expanded, } @@ -78,7 +79,6 @@ impl Sandbox for DropDownExample { .on_dismiss(Message::Dismiss) .alignment(drop_down::Alignment::Bottom); - Column::new() .padding(20) .width(Length::Fill) diff --git a/src/core/mod.rs b/src/core/mod.rs index a4d54d3b..55b6d99e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -21,4 +21,4 @@ pub mod time; pub mod offset; #[cfg(feature = "drop_down")] -pub mod alignment; \ No newline at end of file +pub mod alignment; diff --git a/src/lib.rs b/src/lib.rs index 21ea6b87..94be94b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,9 +170,7 @@ mod platform { #[doc(no_inline)] #[cfg(feature = "drop_down")] - pub use { - crate::native::drop_down, drop_down::DropDown, - }; + pub use {crate::native::drop_down, drop_down::DropDown}; } #[doc(no_inline)] diff --git a/src/native/drop_down.rs b/src/native/drop_down.rs index 4679be20..af9b4a29 100644 --- a/src/native/drop_down.rs +++ b/src/native/drop_down.rs @@ -86,7 +86,6 @@ where } } - impl<'a, Message, Theme, Renderer> Widget for DropDown<'a, Message, Theme, Renderer> where diff --git a/src/native/mod.rs b/src/native/mod.rs index 3d48b225..a4c87273 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -149,4 +149,4 @@ pub mod drop_down; #[cfg(feature = "drop_down")] /// A drop down menu pub type DropDown<'a, Overlay, Message, Renderer> = - drop_down::DropDown<'a, Overlay, Message, Renderer>; \ No newline at end of file + drop_down::DropDown<'a, Overlay, Message, Renderer>; From b89482caf4d16ace5478d96aa4b811453023e81e Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Sat, 17 Feb 2024 18:14:03 +0100 Subject: [PATCH 4/4] fix clippy --- src/core/alignment.rs | 2 +- src/core/offset.rs | 3 ++- src/native/drop_down.rs | 18 +++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/core/alignment.rs b/src/core/alignment.rs index 044eba1a..8ca3e6af 100644 --- a/src/core/alignment.rs +++ b/src/core/alignment.rs @@ -10,7 +10,7 @@ /// +-----------+-----------+-----------+ /// ``` #[allow(missing_docs)] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Alignment { TopStart, Top, diff --git a/src/core/offset.rs b/src/core/offset.rs index eafee04b..1b424b14 100644 --- a/src/core/offset.rs +++ b/src/core/offset.rs @@ -13,8 +13,9 @@ pub struct Offset { impl Offset { /// Construct a new [`Offset`] + #[must_use] pub fn new(x: f32, y: f32) -> Self { - Offset { x, y } + Self { x, y } } } diff --git a/src/native/drop_down.rs b/src/native/drop_down.rs index af9b4a29..2ede29cb 100644 --- a/src/native/drop_down.rs +++ b/src/native/drop_down.rs @@ -1,4 +1,6 @@ -#![allow(missing_docs)] +//! Drop down menu widget +//! +//! *This API requires the following crate features to be activated: `drop_down`* use iced::{ self, @@ -16,7 +18,7 @@ use iced::{ pub use crate::core::{alignment::Alignment, offset::Offset}; -/// Drop down menu +/// Customizable drop down menu widget pub struct DropDown<'a, Message, Theme = iced::Theme, Renderer = iced::Renderer> where Message: Clone, @@ -37,7 +39,7 @@ where Message: Clone, Renderer: renderer::Renderer, { - /// Create a new DropDown + /// Create a new [`DropDown`] pub fn new(underlay: U, overlay: B, expanded: bool) -> Self where U: Into>, @@ -56,30 +58,35 @@ where } /// The width of the overlay + #[must_use] pub fn width(mut self, width: impl Into) -> Self { self.width = Some(width.into()); self } /// The height of the overlay + #[must_use] pub fn height(mut self, height: impl Into) -> Self { self.height = height.into(); self } /// The alignment of the overlay relative to the underlay + #[must_use] pub fn alignment(mut self, alignment: impl Into) -> Self { self.alignment = alignment.into(); self } /// The offset of the overlay + #[must_use] pub fn offset(mut self, offset: impl Into) -> Self { self.offset = offset.into(); self } /// Send a message when a click occur outside of the overlay when expanded + #[must_use] pub fn on_dismiss(mut self, message: Message) -> Self { self.on_dismiss = Some(message); self @@ -244,6 +251,7 @@ where Message: Clone, Renderer: renderer::Renderer, { + #[allow(clippy::too_many_arguments)] fn new( state: &'b mut Tree, element: &'b mut Element<'a, Message, Theme, Renderer>, @@ -259,11 +267,11 @@ where state, element, on_dismiss, - underlay_bounds, width, + height, alignment, offset, - height, + underlay_bounds, position, } }