Procházet zdrojové kódy

Merge pull request #1696 from pascalbehmenburg/master

add default menu bar in dioxus-desktop to resolve #1691
Jonathan Kelley před 1 rokem
rodič
revize
3498396f08

+ 10 - 0
packages/desktop/src/cfg.rs

@@ -36,6 +36,7 @@ pub struct Config {
     pub(crate) root_name: String,
     pub(crate) background_color: Option<(u8, u8, u8, u8)>,
     pub(crate) last_window_close_behaviour: WindowCloseBehaviour,
+    pub(crate) enable_default_menu_bar: bool,
 }
 
 type DropHandler = Box<dyn Fn(&Window, FileDropEvent) -> bool>;
@@ -65,9 +66,18 @@ impl Config {
             root_name: "main".to_string(),
             background_color: None,
             last_window_close_behaviour: WindowCloseBehaviour::LastWindowExitsApp,
+            enable_default_menu_bar: true,
         }
     }
 
+    /// Set whether the default menu bar should be enabled.
+    ///
+    /// > Note: `enable` is `true` by default. To disable the default menu bar pass `false`.
+    pub fn with_default_menu_bar(mut self, enable: bool) -> Self {
+        self.enable_default_menu_bar = enable;
+        self
+    }
+
     /// set the directory from which assets will be searched in release mode
     pub fn with_resource_directory(mut self, path: impl Into<PathBuf>) -> Self {
         self.resource_dir = Some(path.into());

+ 1 - 0
packages/desktop/src/lib.rs

@@ -46,6 +46,7 @@ use tao::{
     event::{Event, StartCause, WindowEvent},
     event_loop::ControlFlow,
 };
+pub use webview::build_default_menu_bar;
 pub use wry;
 pub use wry::application as tao;
 use wry::application::event_loop::EventLoopBuilder;

+ 65 - 1
packages/desktop/src/webview.rs

@@ -4,6 +4,7 @@ use crate::{desktop_context::UserWindowEvent, Config};
 use tao::event_loop::{EventLoopProxy, EventLoopWindowTarget};
 pub use wry;
 pub use wry::application as tao;
+use wry::application::menu::{MenuBar, MenuItem};
 use wry::application::window::Window;
 use wry::http::Response;
 use wry::webview::{WebContext, WebView, WebViewBuilder};
@@ -13,13 +14,18 @@ pub fn build(
     event_loop: &EventLoopWindowTarget<UserWindowEvent>,
     proxy: EventLoopProxy<UserWindowEvent>,
 ) -> (WebView, WebContext, AssetHandlerRegistry) {
-    let builder = cfg.window.clone();
     let window = builder.with_visible(false).build(event_loop).unwrap();
     let file_handler = cfg.file_drop_handler.take();
     let custom_head = cfg.custom_head.clone();
     let index_file = cfg.custom_index.clone();
     let root_name = cfg.root_name.clone();
 
+    if cfg.enable_default_menu_bar {
+        builder = builder.with_menu(build_default_menu_bar());
+    }
+
+    let window = builder.with_visible(false).build(event_loop).unwrap();
+
     // We assume that if the icon is None in cfg, then the user just didnt set it
     if cfg.window.window.window_icon.is_none() {
         window.set_window_icon(Some(
@@ -129,3 +135,61 @@ pub fn build(
 
     (webview.build().unwrap(), web_context, asset_handlers)
 }
+
+/// Builds a standard menu bar depending on the users platform. It may be used as a starting point
+/// to further customize the menu bar and pass it to a [`WindowBuilder`](tao::window::WindowBuilder).
+/// > Note: The default menu bar enables macOS shortcuts like cut/copy/paste.
+/// > The menu bar differs per platform because of constraints introduced
+/// > by [`MenuItem`](tao::menu::MenuItem).
+pub fn build_default_menu_bar() -> MenuBar {
+    let mut menu_bar = MenuBar::new();
+
+    // since it is uncommon on windows to have an "application menu"
+    // we add a "window" menu to be more consistent across platforms with the standard menu
+    let mut window_menu = MenuBar::new();
+    #[cfg(target_os = "macos")]
+    {
+        window_menu.add_native_item(MenuItem::EnterFullScreen);
+        window_menu.add_native_item(MenuItem::Zoom);
+        window_menu.add_native_item(MenuItem::Separator);
+    }
+
+    window_menu.add_native_item(MenuItem::Hide);
+
+    #[cfg(target_os = "macos")]
+    {
+        window_menu.add_native_item(MenuItem::HideOthers);
+        window_menu.add_native_item(MenuItem::ShowAll);
+    }
+
+    window_menu.add_native_item(MenuItem::Minimize);
+    window_menu.add_native_item(MenuItem::CloseWindow);
+    window_menu.add_native_item(MenuItem::Separator);
+    window_menu.add_native_item(MenuItem::Quit);
+    menu_bar.add_submenu("Window", true, window_menu);
+
+    // since tao supports none of the below items on linux we should only add them on macos/windows
+    #[cfg(not(target_os = "linux"))]
+    {
+        let mut edit_menu = MenuBar::new();
+        #[cfg(target_os = "macos")]
+        {
+            edit_menu.add_native_item(MenuItem::Undo);
+            edit_menu.add_native_item(MenuItem::Redo);
+            edit_menu.add_native_item(MenuItem::Separator);
+        }
+
+        edit_menu.add_native_item(MenuItem::Cut);
+        edit_menu.add_native_item(MenuItem::Copy);
+        edit_menu.add_native_item(MenuItem::Paste);
+
+        #[cfg(target_os = "macos")]
+        {
+            edit_menu.add_native_item(MenuItem::Separator);
+            edit_menu.add_native_item(MenuItem::SelectAll);
+        }
+        menu_bar.add_submenu("Edit", true, edit_menu);
+    }
+
+    menu_bar
+}