From 9fc5ad23edca93553137100d167de7b69e88f785 Mon Sep 17 00:00:00 2001 From: Richard Date: Mon, 5 Jul 2021 16:23:44 -0300 Subject: Initial menu implementation --- native/src/lib.rs | 2 ++ native/src/menu.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 native/src/menu.rs (limited to 'native') diff --git a/native/src/lib.rs b/native/src/lib.rs index cd214e36..56a933f0 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -37,6 +37,7 @@ pub mod clipboard; pub mod event; pub mod keyboard; pub mod layout; +pub mod menu; pub mod mouse; pub mod overlay; pub mod program; @@ -75,6 +76,7 @@ pub use element::Element; pub use event::Event; pub use hasher::Hasher; pub use layout::Layout; +pub use menu::{Menu, MenuEntry}; pub use overlay::Overlay; pub use program::Program; pub use renderer::Renderer; diff --git a/native/src/menu.rs b/native/src/menu.rs new file mode 100644 index 00000000..6c73cb32 --- /dev/null +++ b/native/src/menu.rs @@ -0,0 +1,81 @@ +//! Build menus for your application. +use crate::keyboard::Hotkey; + +/// Menu representation. +/// +/// This can be used by `shell` implementations to create a menu. +#[derive(Debug, Clone, PartialEq)] +pub struct Menu { + items: Vec>, +} + +impl Menu { + /// Creates an empty [`Menu`]. + pub fn new() -> Self { + Menu { items: Vec::new() } + } + + /// Adds an item to the [`Menu`]. + pub fn item>( + mut self, + content: S, + hotkey: impl Into>, + on_activation: Message, + ) -> Self { + let content = content.into(); + let hotkey = hotkey.into(); + + self.items.push(MenuEntry::Item { + on_activation, + content, + hotkey, + }); + self + } + + /// Adds a separator to the [`Menu`]. + pub fn separator(mut self) -> Self { + self.items.push(MenuEntry::Separator); + self + } + + /// Adds a dropdown to the [`Menu`]. + pub fn dropdown>( + mut self, + content: S, + submenu: Menu, + ) -> Self { + let content = content.into(); + + self.items.push(MenuEntry::Dropdown { content, submenu }); + self + } + + /// Returns a [`MenuEntry`] iterator. + pub fn iter(self) -> std::vec::IntoIter> { + self.items.into_iter() + } +} + +/// Represents one of the possible entries used to build a [`Menu`]. +#[derive(Debug, Clone, PartialEq)] +pub enum MenuEntry { + /// Item for a [`Menu`] + Item { + /// The title of the item + content: String, + /// The [`Hotkey`] to activate the item, if any + hotkey: Option, + /// The message generated when the item is activated + on_activation: Message, + }, + /// Dropdown for a [`Menu`] + Dropdown { + /// Title of the dropdown + content: String, + /// The submenu of the dropdown + submenu: Menu, + }, + /// Separator for a [`Menu`] + Separator, +} -- cgit From 1428e9180ae9f4edbf22514bb74c5c7e9df9c712 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 12 Jul 2021 21:38:54 +0200 Subject: Make `Menu` API a bit more functional --- native/src/lib.rs | 2 +- native/src/menu.rs | 75 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 37 deletions(-) (limited to 'native') diff --git a/native/src/lib.rs b/native/src/lib.rs index 56a933f0..564f2514 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -76,7 +76,7 @@ pub use element::Element; pub use event::Event; pub use hasher::Hasher; pub use layout::Layout; -pub use menu::{Menu, MenuEntry}; +pub use menu::Menu; pub use overlay::Overlay; pub use program::Program; pub use renderer::Renderer; diff --git a/native/src/menu.rs b/native/src/menu.rs index 6c73cb32..fe770216 100644 --- a/native/src/menu.rs +++ b/native/src/menu.rs @@ -6,60 +6,35 @@ use crate::keyboard::Hotkey; /// This can be used by `shell` implementations to create a menu. #[derive(Debug, Clone, PartialEq)] pub struct Menu { - items: Vec>, + entries: Vec>, } impl Menu { /// Creates an empty [`Menu`]. pub fn new() -> Self { - Menu { items: Vec::new() } + Self::with_entries(Vec::new()) } - /// Adds an item to the [`Menu`]. - pub fn item>( - mut self, - content: S, - hotkey: impl Into>, - on_activation: Message, - ) -> Self { - let content = content.into(); - let hotkey = hotkey.into(); - - self.items.push(MenuEntry::Item { - on_activation, - content, - hotkey, - }); - self + /// Creates a new [`Menu`] with the given entries. + pub fn with_entries(entries: Vec>) -> Self { + Self { entries } } - /// Adds a separator to the [`Menu`]. - pub fn separator(mut self) -> Self { - self.items.push(MenuEntry::Separator); - self - } - - /// Adds a dropdown to the [`Menu`]. - pub fn dropdown>( - mut self, - content: S, - submenu: Menu, - ) -> Self { - let content = content.into(); - - self.items.push(MenuEntry::Dropdown { content, submenu }); + /// Adds an [`Entry`] to the [`Menu`]. + pub fn push(mut self, entry: Entry) -> Self { + self.entries.push(entry); self } /// Returns a [`MenuEntry`] iterator. - pub fn iter(self) -> std::vec::IntoIter> { - self.items.into_iter() + pub fn iter(self) -> impl Iterator> { + self.entries.into_iter() } } /// Represents one of the possible entries used to build a [`Menu`]. #[derive(Debug, Clone, PartialEq)] -pub enum MenuEntry { +pub enum Entry { /// Item for a [`Menu`] Item { /// The title of the item @@ -79,3 +54,31 @@ pub enum MenuEntry { /// Separator for a [`Menu`] Separator, } + +impl Entry { + /// Creates an [`Entry::Item`]. + pub fn item>( + content: S, + hotkey: impl Into>, + on_activation: Message, + ) -> Self { + let content = content.into(); + let hotkey = hotkey.into(); + + Entry::Item { + content, + hotkey, + on_activation, + } + } + + /// Creates an [`Entry::Dropdown`]. + pub fn dropdown>( + content: S, + submenu: Menu, + ) -> Self { + let content = content.into(); + + Entry::Dropdown { content, submenu } + } +} -- cgit From 735cfb790813c44852612400e31c0190b9c641a6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 12 Jul 2021 21:44:01 +0200 Subject: Move `menu` module from `iced_native` to `iced_core` --- native/src/lib.rs | 6 ++-- native/src/menu.rs | 84 ------------------------------------------------------ 2 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 native/src/menu.rs (limited to 'native') diff --git a/native/src/lib.rs b/native/src/lib.rs index 564f2514..cbb02506 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -37,7 +37,6 @@ pub mod clipboard; pub mod event; pub mod keyboard; pub mod layout; -pub mod menu; pub mod mouse; pub mod overlay; pub mod program; @@ -62,8 +61,8 @@ mod debug; mod debug; pub use iced_core::{ - Align, Background, Color, Font, HorizontalAlignment, Length, Padding, - Point, Rectangle, Size, Vector, VerticalAlignment, + menu, Align, Background, Color, Font, HorizontalAlignment, Length, Menu, + Padding, Point, Rectangle, Size, Vector, VerticalAlignment, }; pub use iced_futures::{executor, futures, Command}; @@ -76,7 +75,6 @@ pub use element::Element; pub use event::Event; pub use hasher::Hasher; pub use layout::Layout; -pub use menu::Menu; pub use overlay::Overlay; pub use program::Program; pub use renderer::Renderer; diff --git a/native/src/menu.rs b/native/src/menu.rs deleted file mode 100644 index fe770216..00000000 --- a/native/src/menu.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! Build menus for your application. -use crate::keyboard::Hotkey; - -/// Menu representation. -/// -/// This can be used by `shell` implementations to create a menu. -#[derive(Debug, Clone, PartialEq)] -pub struct Menu { - entries: Vec>, -} - -impl Menu { - /// Creates an empty [`Menu`]. - pub fn new() -> Self { - Self::with_entries(Vec::new()) - } - - /// Creates a new [`Menu`] with the given entries. - pub fn with_entries(entries: Vec>) -> Self { - Self { entries } - } - - /// Adds an [`Entry`] to the [`Menu`]. - pub fn push(mut self, entry: Entry) -> Self { - self.entries.push(entry); - self - } - - /// Returns a [`MenuEntry`] iterator. - pub fn iter(self) -> impl Iterator> { - self.entries.into_iter() - } -} - -/// Represents one of the possible entries used to build a [`Menu`]. -#[derive(Debug, Clone, PartialEq)] -pub enum Entry { - /// Item for a [`Menu`] - Item { - /// The title of the item - content: String, - /// The [`Hotkey`] to activate the item, if any - hotkey: Option, - /// The message generated when the item is activated - on_activation: Message, - }, - /// Dropdown for a [`Menu`] - Dropdown { - /// Title of the dropdown - content: String, - /// The submenu of the dropdown - submenu: Menu, - }, - /// Separator for a [`Menu`] - Separator, -} - -impl Entry { - /// Creates an [`Entry::Item`]. - pub fn item>( - content: S, - hotkey: impl Into>, - on_activation: Message, - ) -> Self { - let content = content.into(); - let hotkey = hotkey.into(); - - Entry::Item { - content, - hotkey, - on_activation, - } - } - - /// Creates an [`Entry::Dropdown`]. - pub fn dropdown>( - content: S, - submenu: Menu, - ) -> Self { - let content = content.into(); - - Entry::Dropdown { content, submenu } - } -} -- cgit From b57d567981bb7ef5f9ff397c210778f211d2de5b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 12 Jul 2021 22:01:57 +0200 Subject: Use `bitflags` for `keyboard::Modifiers` --- native/src/widget/text_input.rs | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 20117fa0..f06f057b 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -362,7 +362,7 @@ where Event::Keyboard(keyboard::Event::CharacterReceived(c)) if self.state.is_focused && self.state.is_pasting.is_none() - && !self.state.keyboard_modifiers.is_command_pressed() + && !self.state.keyboard_modifiers.command() && !c.is_control() => { let mut editor = @@ -450,7 +450,7 @@ where if platform::is_jump_modifier_pressed(modifiers) && !self.is_secure { - if modifiers.shift { + if modifiers.shift() { self.state .cursor .select_left_by_words(&self.value); @@ -459,7 +459,7 @@ where .cursor .move_left_by_words(&self.value); } - } else if modifiers.shift { + } else if modifiers.shift() { self.state.cursor.select_left(&self.value) } else { self.state.cursor.move_left(&self.value); @@ -469,7 +469,7 @@ where if platform::is_jump_modifier_pressed(modifiers) && !self.is_secure { - if modifiers.shift { + if modifiers.shift() { self.state .cursor .select_right_by_words(&self.value); @@ -478,14 +478,14 @@ where .cursor .move_right_by_words(&self.value); } - } else if modifiers.shift { + } else if modifiers.shift() { self.state.cursor.select_right(&self.value) } else { self.state.cursor.move_right(&self.value); } } keyboard::KeyCode::Home => { - if modifiers.shift { + if modifiers.shift() { self.state.cursor.select_range( self.state.cursor.start(&self.value), 0, @@ -495,7 +495,7 @@ where } } keyboard::KeyCode::End => { - if modifiers.shift { + if modifiers.shift() { self.state.cursor.select_range( self.state.cursor.start(&self.value), self.value.len(), @@ -505,10 +505,7 @@ where } } keyboard::KeyCode::C - if self - .state - .keyboard_modifiers - .is_command_pressed() => + if self.state.keyboard_modifiers.command() => { match self.state.cursor.selection(&self.value) { Some((start, end)) => { @@ -520,10 +517,7 @@ where } } keyboard::KeyCode::X - if self - .state - .keyboard_modifiers - .is_command_pressed() => + if self.state.keyboard_modifiers.command() => { match self.state.cursor.selection(&self.value) { Some((start, end)) => { @@ -545,7 +539,7 @@ where messages.push(message); } keyboard::KeyCode::V => { - if self.state.keyboard_modifiers.is_command_pressed() { + if self.state.keyboard_modifiers.command() { let content = match self.state.is_pasting.take() { Some(content) => content, None => { @@ -576,10 +570,7 @@ where } } keyboard::KeyCode::A - if self - .state - .keyboard_modifiers - .is_command_pressed() => + if self.state.keyboard_modifiers.command() => { self.state.cursor.select_all(&self.value); } @@ -858,9 +849,9 @@ mod platform { pub fn is_jump_modifier_pressed(modifiers: keyboard::Modifiers) -> bool { if cfg!(target_os = "macos") { - modifiers.alt + modifiers.alt() } else { - modifiers.control + modifiers.control() } } } -- cgit From 5df2a92f28be1d53d32d5b42a6645459b7d78efe Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 13 Jul 2021 21:15:07 +0200 Subject: Force `Application::Message` to implement `Clone` A `Message` should represent an application event (e.g. user interactions, command results, subscription results...). Therefore, it should always consist of pure, cloneable data. --- native/src/program.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'native') diff --git a/native/src/program.rs b/native/src/program.rs index 066c29d8..75fab094 100644 --- a/native/src/program.rs +++ b/native/src/program.rs @@ -11,7 +11,7 @@ pub trait Program: Sized { type Renderer: Renderer; /// The type of __messages__ your [`Program`] will produce. - type Message: std::fmt::Debug + Send; + type Message: std::fmt::Debug + Clone + Send; /// The type of [`Clipboard`] your [`Program`] will use. type Clipboard: Clipboard; -- cgit