title_bar: Factor out application menu into its own component (#13947)

Marshall Bowers created

This PR factors out the application menu in the title bar into its own
component.

Release Notes:

- N/A

Change summary

crates/title_bar/src/application_menu.rs | 181 ++++++++++++++++++++++++++
crates/title_bar/src/title_bar.rs        | 178 +------------------------
2 files changed, 188 insertions(+), 171 deletions(-)

Detailed changes

crates/title_bar/src/application_menu.rs 🔗

@@ -0,0 +1,181 @@
+use settings::Settings;
+use theme::ThemeSettings;
+use ui::{prelude::*, ContextMenu, PopoverMenu, Tooltip};
+
+#[derive(IntoElement)]
+pub struct ApplicationMenu;
+
+impl ApplicationMenu {
+    pub fn new() -> Self {
+        Self
+    }
+}
+
+impl RenderOnce for ApplicationMenu {
+    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+        let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
+        let font = cx.text_style().font();
+        let font_id = cx.text_system().resolve_font(&font);
+        let width = cx
+            .text_system()
+            .typographic_bounds(font_id, ui_font_size, 'm')
+            .unwrap()
+            .size
+            .width
+            * 3.0;
+
+        PopoverMenu::new("application-menu")
+            .menu(move |cx| {
+                let width = width;
+                ContextMenu::build(cx, move |menu, _cx| {
+                    let width = width;
+                    menu.header("Workspace")
+                        .action("Open Command Palette", Box::new(command_palette::Toggle))
+                        .custom_row(move |cx| {
+                            div()
+                                .w_full()
+                                .flex()
+                                .flex_row()
+                                .justify_between()
+                                .cursor(gpui::CursorStyle::Arrow)
+                                .child(Label::new("Buffer Font Size"))
+                                .child(
+                                    div()
+                                        .flex()
+                                        .flex_row()
+                                        .child(div().w(px(16.0)))
+                                        .child(
+                                            IconButton::new(
+                                                "reset-buffer-zoom",
+                                                IconName::RotateCcw,
+                                            )
+                                            .on_click(
+                                                |_, cx| {
+                                                    cx.dispatch_action(Box::new(
+                                                        zed_actions::ResetBufferFontSize,
+                                                    ))
+                                                },
+                                            ),
+                                        )
+                                        .child(
+                                            IconButton::new("--buffer-zoom", IconName::Dash)
+                                                .on_click(|_, cx| {
+                                                    cx.dispatch_action(Box::new(
+                                                        zed_actions::DecreaseBufferFontSize,
+                                                    ))
+                                                }),
+                                        )
+                                        .child(
+                                            div()
+                                                .w(width)
+                                                .flex()
+                                                .flex_row()
+                                                .justify_around()
+                                                .child(Label::new(
+                                                    theme::get_buffer_font_size(cx).to_string(),
+                                                )),
+                                        )
+                                        .child(
+                                            IconButton::new("+-buffer-zoom", IconName::Plus)
+                                                .on_click(|_, cx| {
+                                                    cx.dispatch_action(Box::new(
+                                                        zed_actions::IncreaseBufferFontSize,
+                                                    ))
+                                                }),
+                                        ),
+                                )
+                                .into_any_element()
+                        })
+                        .custom_row(move |cx| {
+                            div()
+                                .w_full()
+                                .flex()
+                                .flex_row()
+                                .justify_between()
+                                .cursor(gpui::CursorStyle::Arrow)
+                                .child(Label::new("UI Font Size"))
+                                .child(
+                                    div()
+                                        .flex()
+                                        .flex_row()
+                                        .child(
+                                            IconButton::new("reset-ui-zoom", IconName::RotateCcw)
+                                                .on_click(|_, cx| {
+                                                    cx.dispatch_action(Box::new(
+                                                        zed_actions::ResetUiFontSize,
+                                                    ))
+                                                }),
+                                        )
+                                        .child(
+                                            IconButton::new("--ui-zoom", IconName::Dash).on_click(
+                                                |_, cx| {
+                                                    cx.dispatch_action(Box::new(
+                                                        zed_actions::DecreaseUiFontSize,
+                                                    ))
+                                                },
+                                            ),
+                                        )
+                                        .child(
+                                            div()
+                                                .w(width)
+                                                .flex()
+                                                .flex_row()
+                                                .justify_around()
+                                                .child(Label::new(
+                                                    theme::get_ui_font_size(cx).to_string(),
+                                                )),
+                                        )
+                                        .child(
+                                            IconButton::new("+-ui-zoom", IconName::Plus).on_click(
+                                                |_, cx| {
+                                                    cx.dispatch_action(Box::new(
+                                                        zed_actions::IncreaseUiFontSize,
+                                                    ))
+                                                },
+                                            ),
+                                        ),
+                                )
+                                .into_any_element()
+                        })
+                        .header("Project")
+                        .action(
+                            "Add Folder to Project...",
+                            Box::new(workspace::AddFolderToProject),
+                        )
+                        .action("Open a new Project...", Box::new(workspace::Open))
+                        .action(
+                            "Open Recent Projects...",
+                            Box::new(recent_projects::OpenRecent {
+                                create_new_window: false,
+                            }),
+                        )
+                        .header("Help")
+                        .action("About Zed", Box::new(zed_actions::About))
+                        .action("Welcome", Box::new(workspace::Welcome))
+                        .link(
+                            "Documentation",
+                            Box::new(zed_actions::OpenBrowser {
+                                url: "https://zed.dev/docs".into(),
+                            }),
+                        )
+                        .action("Give Feedback", Box::new(feedback::GiveFeedback))
+                        .action("Check for Updates", Box::new(auto_update::Check))
+                        .action("View Telemetry", Box::new(zed_actions::OpenTelemetryLog))
+                        .action(
+                            "View Dependency Licenses",
+                            Box::new(zed_actions::OpenLicenses),
+                        )
+                        .separator()
+                        .action("Quit", Box::new(zed_actions::Quit))
+                })
+                .into()
+            })
+            .trigger(
+                IconButton::new("application-menu", ui::IconName::Menu)
+                    .style(ButtonStyle::Subtle)
+                    .tooltip(|cx| Tooltip::text("Open Application Menu", cx))
+                    .icon_size(IconSize::Small),
+            )
+            .into_any_element()
+    }
+}

crates/title_bar/src/title_bar.rs 🔗

@@ -1,8 +1,10 @@
+mod application_menu;
 mod call_controls;
 mod collab;
 mod platforms;
 mod window_controls;
 
+use crate::application_menu::ApplicationMenu;
 use crate::platforms::{platform_linux, platform_mac, platform_windows};
 use auto_update::AutoUpdateStatus;
 use call::{ActiveCall, ParticipantLocation};
@@ -16,10 +18,9 @@ use gpui::{
 use project::{Project, RepositoryEntry};
 use recent_projects::RecentProjects;
 use rpc::proto::DevServerStatus;
-use settings::Settings;
 use smallvec::SmallVec;
 use std::sync::Arc;
-use theme::{ActiveTheme, ThemeSettings};
+use theme::ActiveTheme;
 use ui::{
     h_flex, prelude::*, Avatar, Button, ButtonLike, ButtonStyle, ContextMenu, Icon, IconButton,
     IconName, Indicator, PopoverMenu, TintColor, Tooltip,
@@ -122,7 +123,10 @@ impl Render for TitleBar {
                         .child(
                             h_flex()
                                 .gap_1()
-                                .children(self.render_application_menu(cx))
+                                .children(match self.platform_style {
+                                    PlatformStyle::Mac => None,
+                                    PlatformStyle::Linux | PlatformStyle::Windows => Some(ApplicationMenu::new())
+                                })
                                 .children(self.render_project_host(cx))
                                 .child(self.render_project_name(cx))
                                 .children(self.render_project_branch(cx))
@@ -494,174 +498,6 @@ impl TitleBar {
         self
     }
 
-    pub fn render_application_menu(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
-        cfg!(not(target_os = "macos")).then(|| {
-            let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
-            let font = cx.text_style().font();
-            let font_id = cx.text_system().resolve_font(&font);
-            let width = cx
-                .text_system()
-                .typographic_bounds(font_id, ui_font_size, 'm')
-                .unwrap()
-                .size
-                .width
-                * 3.0;
-
-            PopoverMenu::new("application-menu")
-                .menu(move |cx| {
-                    let width = width;
-                    ContextMenu::build(cx, move |menu, _cx| {
-                        let width = width;
-                        menu.header("Workspace")
-                            .action("Open Command Palette", Box::new(command_palette::Toggle))
-                            .custom_row(move |cx| {
-                                div()
-                                    .w_full()
-                                    .flex()
-                                    .flex_row()
-                                    .justify_between()
-                                    .cursor(gpui::CursorStyle::Arrow)
-                                    .child(Label::new("Buffer Font Size"))
-                                    .child(
-                                        div()
-                                            .flex()
-                                            .flex_row()
-                                            .child(div().w(px(16.0)))
-                                            .child(
-                                                IconButton::new(
-                                                    "reset-buffer-zoom",
-                                                    IconName::RotateCcw,
-                                                )
-                                                .on_click(|_, cx| {
-                                                    cx.dispatch_action(Box::new(
-                                                        zed_actions::ResetBufferFontSize,
-                                                    ))
-                                                }),
-                                            )
-                                            .child(
-                                                IconButton::new("--buffer-zoom", IconName::Dash)
-                                                    .on_click(|_, cx| {
-                                                        cx.dispatch_action(Box::new(
-                                                            zed_actions::DecreaseBufferFontSize,
-                                                        ))
-                                                    }),
-                                            )
-                                            .child(
-                                                div()
-                                                    .w(width)
-                                                    .flex()
-                                                    .flex_row()
-                                                    .justify_around()
-                                                    .child(Label::new(
-                                                        theme::get_buffer_font_size(cx).to_string(),
-                                                    )),
-                                            )
-                                            .child(
-                                                IconButton::new("+-buffer-zoom", IconName::Plus)
-                                                    .on_click(|_, cx| {
-                                                        cx.dispatch_action(Box::new(
-                                                            zed_actions::IncreaseBufferFontSize,
-                                                        ))
-                                                    }),
-                                            ),
-                                    )
-                                    .into_any_element()
-                            })
-                            .custom_row(move |cx| {
-                                div()
-                                    .w_full()
-                                    .flex()
-                                    .flex_row()
-                                    .justify_between()
-                                    .cursor(gpui::CursorStyle::Arrow)
-                                    .child(Label::new("UI Font Size"))
-                                    .child(
-                                        div()
-                                            .flex()
-                                            .flex_row()
-                                            .child(
-                                                IconButton::new(
-                                                    "reset-ui-zoom",
-                                                    IconName::RotateCcw,
-                                                )
-                                                .on_click(|_, cx| {
-                                                    cx.dispatch_action(Box::new(
-                                                        zed_actions::ResetUiFontSize,
-                                                    ))
-                                                }),
-                                            )
-                                            .child(
-                                                IconButton::new("--ui-zoom", IconName::Dash)
-                                                    .on_click(|_, cx| {
-                                                        cx.dispatch_action(Box::new(
-                                                            zed_actions::DecreaseUiFontSize,
-                                                        ))
-                                                    }),
-                                            )
-                                            .child(
-                                                div()
-                                                    .w(width)
-                                                    .flex()
-                                                    .flex_row()
-                                                    .justify_around()
-                                                    .child(Label::new(
-                                                        theme::get_ui_font_size(cx).to_string(),
-                                                    )),
-                                            )
-                                            .child(
-                                                IconButton::new("+-ui-zoom", IconName::Plus)
-                                                    .on_click(|_, cx| {
-                                                        cx.dispatch_action(Box::new(
-                                                            zed_actions::IncreaseUiFontSize,
-                                                        ))
-                                                    }),
-                                            ),
-                                    )
-                                    .into_any_element()
-                            })
-                            .header("Project")
-                            .action(
-                                "Add Folder to Project...",
-                                Box::new(workspace::AddFolderToProject),
-                            )
-                            .action("Open a new Project...", Box::new(workspace::Open))
-                            .action(
-                                "Open Recent Projects...",
-                                Box::new(recent_projects::OpenRecent {
-                                    create_new_window: false,
-                                }),
-                            )
-                            .header("Help")
-                            .action("About Zed", Box::new(zed_actions::About))
-                            .action("Welcome", Box::new(workspace::Welcome))
-                            .link(
-                                "Documentation",
-                                Box::new(zed_actions::OpenBrowser {
-                                    url: "https://zed.dev/docs".into(),
-                                }),
-                            )
-                            .action("Give Feedback", Box::new(feedback::GiveFeedback))
-                            .action("Check for Updates", Box::new(auto_update::Check))
-                            .action("View Telemetry", Box::new(zed_actions::OpenTelemetryLog))
-                            .action(
-                                "View Dependency Licenses",
-                                Box::new(zed_actions::OpenLicenses),
-                            )
-                            .separator()
-                            .action("Quit", Box::new(zed_actions::Quit))
-                    })
-                    .into()
-                })
-                .trigger(
-                    IconButton::new("application-menu", ui::IconName::Menu)
-                        .style(ButtonStyle::Subtle)
-                        .tooltip(|cx| Tooltip::text("Open Application Menu", cx))
-                        .icon_size(IconSize::Small),
-                )
-                .into_any_element()
-        })
-    }
-
     pub fn render_project_host(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
         if let Some(dev_server) =
             self.project