add documentation

This commit is contained in:
amrbashir 2022-05-06 22:57:58 +02:00
parent 2ccd400497
commit 17ae5366c7
No known key found for this signature in database
GPG key ID: BBD7A47A2003FF33
5 changed files with 135 additions and 6 deletions

View file

@ -1,6 +1,7 @@
[package] [package]
name = "menu-rs" name = "menu-rs"
version = "0.0.0" version = "0.0.0"
description = "Cross-platform menu creation library."
edition = "2021" edition = "2021"
[dependencies] [dependencies]

34
README.md Normal file
View file

@ -0,0 +1,34 @@
# menu-rs
Cross-platform menu creation library.
## Example
Create the root menu and add submenus and men items.
```rs
let mut menu = Menu::new();
let file_menu = menu.add_submenu("File", true);
let open_item = file_menu.add_text_item("Open", true);
let save_item = file_menu.add_text_item("Save", true);
let edit_menu = menu.add_submenu("Edit", true);
let copy_item = file_menu.add_text_item("Copy", true);
let cut_item = file_menu.add_text_item("Cut", true);
#[cfg(target_os = "windows")]
menu.init_for_hwnd(window.hwnd() as isize);
#[cfg(target_os = "linux")]
menu.init_for_gtk_window(&gtk_window);
```
Then listen for the events
```rs
if let Ok(event) = menu_event_receiver().try_recv() {
match event.id {
_ if event.id == save_item.id() => {
println!("Save menu item activated");
},
_ => {}
}
}
```

View file

@ -48,9 +48,9 @@ fn main() {
if let Ok(event) = menu_channel.try_recv() { if let Ok(event) = menu_channel.try_recv() {
match event.id { match event.id {
_ if event.id == save_item.id() => { _ if event.id == save_item.id() => {
println!("Save menu item triggered"); println!("Save menu item activated!");
counter += 1; counter += 1;
save_item.set_label(format!("Save triggered {counter} times")); save_item.set_label(format!("Save activated {counter} times"));
if !open_item_disabled { if !open_item_disabled {
println!("Open item disabled!"); println!("Open item disabled!");

View file

@ -41,9 +41,9 @@ fn main() {
if let Ok(event) = menu_channel.try_recv() { if let Ok(event) = menu_channel.try_recv() {
match event.id { match event.id {
_ if event.id == save_item.id() => { _ if event.id == save_item.id() => {
println!("Save menu item triggered"); println!("Save menu item activated!");
counter += 1; counter += 1;
save_item.set_label(format!("Save triggered {counter} times")); save_item.set_label(format!("Save activated {counter} times"));
if !open_item_disabled { if !open_item_disabled {
println!("Open item disabled!"); println!("Open item disabled!");

View file

@ -1,3 +1,63 @@
//! menu-rs is a cross-platform menu creation library.
//!
//! # Creating root menus
//!
//! Before you can add submenus and menu items, you first need a root or a base menu.
//! ```no_run
//! let mut menu = Menu::new();
//! ```
//!
//! # Adding submens to the root menu
//!
//! Once you have a root menu you can start adding [`Submenu`]s by using [`Menu::add_submenu`].
//! ```no_run
//! let mut menu = Menu::new();
//! let file_menu = menu.add_submenu("File", true);
//! let edit_menu = menu.add_submenu("Edit", true);
//! ```
//!
//! # Aadding menu items and submenus within another submenu
//!
//! Once you have a [`Submenu`] you can star creating more [`Submenu`]s or [`TextMenuItem`]s.
//! ```no_run
//! let mut menu = Menu::new();
//!
//! let file_menu = menu.add_submenu("File", true);
//! let open_item = file_menu.add_text_item("Open", true);
//! let save_item = file_menu.add_text_item("Save", true);
//!
//! let edit_menu = menu.add_submenu("Edit", true);
//! let copy_item = file_menu.add_text_item("Copy", true);
//! let cut_item = file_menu.add_text_item("Cut", true);
//! ```
//!
//! # Add your root menu to a Window (Windows and Linux Only)
//!
//! You can use [`Menu`] to display a top menu in a Window on Windows and Linux.
//! ```no_run
//! let mut menu = Menu::new();
//! // --snip--
//! #[cfg(target_os = "windows")]
//! menu.init_for_hwnd(window.hwnd() as isize);
//! #[cfg(target_os = "linux")]
//! menu.init_for_gtk_window(&gtk_window);
//! ```
//!
//! # Processing menu events
//!
//! You can use [`menu_event_receiver`] to get a reference to the [`MenuEventReceiver`]
//! which you can use to listen to events when a menu item is activated
//! ```no_run
//! if let Ok(event) = menu_event_receiver().try_recv() {
//! match event.id {
//! _ if event.id == save_item.id() => {
//! println!("Save menu item activated");
//! },
//! _ => {}
//! }
//! }
//! ```
use crossbeam_channel::{unbounded, Receiver, Sender}; use crossbeam_channel::{unbounded, Receiver, Sender};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -6,27 +66,46 @@ mod util;
static MENU_CHANNEL: Lazy<(Sender<MenuEvent>, Receiver<MenuEvent>)> = Lazy::new(|| unbounded()); static MENU_CHANNEL: Lazy<(Sender<MenuEvent>, Receiver<MenuEvent>)> = Lazy::new(|| unbounded());
/// Event channel for receiving menu events. /// A type alias to the receiver of the menu events channel.
pub fn menu_event_receiver<'a>() -> &'a Receiver<MenuEvent> { pub type MenuEventReceiver = Receiver<MenuEvent>;
/// Gets a reference to the event channel's [MenuEventReceiver]
/// which can be used to listen for menu events.
pub fn menu_event_receiver<'a>() -> &'a MenuEventReceiver {
&MENU_CHANNEL.1 &MENU_CHANNEL.1
} }
/// Describes a menu event emitted when a menu item is activated /// Describes a menu event emitted when a menu item is activated
pub struct MenuEvent { pub struct MenuEvent {
/// Id of the menu item which triggered this event
pub id: u64, pub id: u64,
} }
/// This is the root menu type to which you can add
/// more submenus and later be add to the top of a window (on Windows and Linux)
/// or used as the menubar menu (on macOS) or displayed as a popup menu.
///
/// # Example
///
/// ```
/// let mut menu = Menu::new();
/// let file_menu = menu.add_submenu("File", true);
/// let edit_menu = menu.add_submenu("Edit", true);
/// ```
pub struct Menu(platform_impl::Menu); pub struct Menu(platform_impl::Menu);
impl Menu { impl Menu {
/// Creates a new root menu.
pub fn new() -> Self { pub fn new() -> Self {
Self(platform_impl::Menu::new()) Self(platform_impl::Menu::new())
} }
/// Creates a new [`Submenu`] whithin this menu.
pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu { pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu {
Submenu(self.0.add_submenu(label, enabled)) Submenu(self.0.add_submenu(label, enabled))
} }
/// Adds this menu to a [`gtk::Window`].
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn init_for_gtk_window<W>(&self, w: &W) pub fn init_for_gtk_window<W>(&self, w: &W)
where where
@ -35,6 +114,7 @@ impl Menu {
self.0.init_for_gtk_window(w) self.0.init_for_gtk_window(w)
} }
/// Adds this menu to a win32 window.
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn init_for_hwnd(&self, hwnd: isize) { pub fn init_for_hwnd(&self, hwnd: isize) {
self.0.init_for_hwnd(hwnd) self.0.init_for_hwnd(hwnd)
@ -42,53 +122,67 @@ impl Menu {
} }
#[derive(Clone)] #[derive(Clone)]
/// This is a submenu within another [`Submenu`] or [`Menu`].
pub struct Submenu(platform_impl::Submenu); pub struct Submenu(platform_impl::Submenu);
impl Submenu { impl Submenu {
/// Gets the submenus's current label.
pub fn label(&self) -> String { pub fn label(&self) -> String {
self.0.label() self.0.label()
} }
/// Sets a new label for the submenu.
pub fn set_label(&mut self, label: impl AsRef<str>) { pub fn set_label(&mut self, label: impl AsRef<str>) {
self.0.set_label(label) self.0.set_label(label)
} }
/// Gets the submenu's current state, whether enabled or not.
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {
self.0.enabled() self.0.enabled()
} }
/// Enables or disables the submenu
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) {
self.0.set_enabled(enabled) self.0.set_enabled(enabled)
} }
/// Creates a new [`Submenu`] whithin this submenu.
pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu { pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu {
Submenu(self.0.add_submenu(label, enabled)) Submenu(self.0.add_submenu(label, enabled))
} }
/// Creates a new [`TextMenuItem`] whithin this submenu.
pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem { pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem {
TextMenuItem(self.0.add_text_item(label, enabled)) TextMenuItem(self.0.add_text_item(label, enabled))
} }
} }
/// This is a Text menu item within a [`Submenu`].
#[derive(Clone)] #[derive(Clone)]
pub struct TextMenuItem(platform_impl::TextMenuItem); pub struct TextMenuItem(platform_impl::TextMenuItem);
impl TextMenuItem { impl TextMenuItem {
/// Gets the menu item's current label.
pub fn label(&self) -> String { pub fn label(&self) -> String {
self.0.label() self.0.label()
} }
/// Sets a new label for the menu item.
pub fn set_label(&mut self, label: impl AsRef<str>) { pub fn set_label(&mut self, label: impl AsRef<str>) {
self.0.set_label(label) self.0.set_label(label)
} }
/// Gets the menu item's current state, whether enabled or not.
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {
self.0.enabled() self.0.enabled()
} }
/// Enables or disables the menu item.
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) {
self.0.set_enabled(enabled) self.0.set_enabled(enabled)
} }
/// Gets the unique id for this menu item.
pub fn id(&self) -> u64 { pub fn id(&self) -> u64 {
self.0.id() self.0.id()
} }