feat: responsive menu bar

This commit is contained in:
Ashley Wulber 2025-04-15 17:38:49 -04:00 • committed by Jeremy Soller
parent 623645c829
commit 97f87809b9
4 changed files with 967 additions and 212 deletions

1022
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -49,7 +49,7 @@ features = ["monospace_fallback", "shape-run-cache"]
[dependencies.libcosmic] [dependencies.libcosmic]
git = "https://github.com/pop-os/libcosmic.git" git = "https://github.com/pop-os/libcosmic.git"
default-features = false default-features = false
features = ["a11y", "multi-window", "tokio", "winit"] features = ["a11y", "multi-window", "tokio", "winit", "surface-message"]
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
fork = "0.2" fork = "0.2"

View file

@ -2642,7 +2642,7 @@ impl Application for App {
} }
fn header_start(&self) -> Vec<Element<Self::Message>> { fn header_start(&self) -> Vec<Element<Self::Message>> {
vec![menu_bar(&self.config, &self.key_binds)] vec![menu_bar(&self.core, &self.config, &self.key_binds)]
} }
fn header_end(&self) -> Vec<Element<Self::Message>> { fn header_end(&self) -> Vec<Element<Self::Message>> {

View file

@ -3,6 +3,7 @@
use cosmic::widget::menu::key_bind::KeyBind; use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::widget::menu::{items as menu_items, menu_button, root as menu_root, Item as MenuItem}; use cosmic::widget::menu::{items as menu_items, menu_button, root as menu_root, Item as MenuItem};
use cosmic::{ use cosmic::{
app::Core,
iced::{ iced::{
widget::{column, horizontal_space}, widget::{column, horizontal_space},
Background, Length, Background, Length,
@ -11,14 +12,17 @@ use cosmic::{
widget::{ widget::{
self, divider, self, divider,
menu::{ItemHeight, ItemWidth, MenuBar, Tree as MenuTree}, menu::{ItemHeight, ItemWidth, MenuBar, Tree as MenuTree},
segmented_button, responsive_menu_bar, segmented_button,
}, },
Element, Element,
}; };
use std::collections::HashMap; use std::{collections::HashMap, sync::LazyLock};
use crate::{fl, Action, ColorSchemeId, ColorSchemeKind, Config, Message}; use crate::{fl, Action, ColorSchemeId, ColorSchemeKind, Config, Message};
static MENU_ID: LazyLock<cosmic::widget::Id> =
LazyLock::new(|| cosmic::widget::Id::new("responsive-menu"));
pub fn context_menu<'a>( pub fn context_menu<'a>(
config: &Config, config: &Config,
key_binds: &HashMap<KeyBind, Action>, key_binds: &HashMap<KeyBind, Action>,
@ -143,7 +147,11 @@ pub fn color_scheme_menu<'a>(
.into() .into()
} }
pub fn menu_bar<'a>(config: &Config, key_binds: &HashMap<KeyBind, Action>) -> Element<'a, Message> { pub fn menu_bar<'a>(
core: &Core,
config: &Config,
key_binds: &HashMap<KeyBind, Action>,
) -> Element<'a, Message> {
let mut profile_items = Vec::with_capacity(config.profiles.len()); let mut profile_items = Vec::with_capacity(config.profiles.len());
for (name, id) in config.profile_names() { for (name, id) in config.profile_names() {
profile_items.push(MenuItem::Button(name, None, Action::ProfileOpen(id))); profile_items.push(MenuItem::Button(name, None, Action::ProfileOpen(id)));
@ -151,73 +159,74 @@ pub fn menu_bar<'a>(config: &Config, key_binds: &HashMap<KeyBind, Action>) -> El
//TODO: what to do if there are no profiles? //TODO: what to do if there are no profiles?
MenuBar::new(vec![ responsive_menu_bar()
MenuTree::with_children( .item_height(ItemHeight::Dynamic(40))
menu_root(fl!("file")), .item_width(ItemWidth::Uniform(240))
menu_items( .spacing(4.0)
key_binds, .into_element(
vec![ core,
MenuItem::Button(fl!("new-tab"), None, Action::TabNew), key_binds,
MenuItem::Button(fl!("new-window"), None, Action::WindowNew), MENU_ID.clone(),
MenuItem::Divider, Message::Surface,
MenuItem::Folder(fl!("profile"), profile_items), vec![
MenuItem::Button(fl!("menu-profiles"), None, Action::Profiles), (
MenuItem::Divider, fl!("file"),
MenuItem::Button(fl!("close-tab"), None, Action::TabClose), vec![
MenuItem::Divider, MenuItem::Button(fl!("new-tab"), None, Action::TabNew),
MenuItem::Button(fl!("quit"), None, Action::WindowClose), MenuItem::Button(fl!("new-window"), None, Action::WindowNew),
], MenuItem::Divider,
), MenuItem::Folder(fl!("profile"), profile_items),
), MenuItem::Button(fl!("menu-profiles"), None, Action::Profiles),
MenuTree::with_children( MenuItem::Divider,
menu_root(fl!("edit")), MenuItem::Button(fl!("close-tab"), None, Action::TabClose),
menu_items( MenuItem::Divider,
key_binds, MenuItem::Button(fl!("quit"), None, Action::WindowClose),
vec![ ],
MenuItem::Button(fl!("copy"), None, Action::Copy), ),
MenuItem::Button(fl!("paste"), None, Action::Paste), (
MenuItem::Button(fl!("select-all"), None, Action::SelectAll), fl!("edit"),
MenuItem::Divider, vec![
MenuItem::Button(fl!("clear-scrollback"), None, Action::ClearScrollback), MenuItem::Button(fl!("copy"), None, Action::Copy),
MenuItem::Divider, MenuItem::Button(fl!("paste"), None, Action::Paste),
MenuItem::Button(fl!("find"), None, Action::Find), MenuItem::Button(fl!("select-all"), None, Action::SelectAll),
], MenuItem::Divider,
), MenuItem::Button(fl!("clear-scrollback"), None, Action::ClearScrollback),
), MenuItem::Divider,
MenuTree::with_children( MenuItem::Button(fl!("find"), None, Action::Find),
menu_root(fl!("view")), ],
menu_items( ),
key_binds, (
vec![ fl!("view"),
MenuItem::Button(fl!("zoom-in"), None, Action::ZoomIn), vec![
MenuItem::Button(fl!("zoom-reset"), None, Action::ZoomReset), MenuItem::Button(fl!("zoom-in"), None, Action::ZoomIn),
MenuItem::Button(fl!("zoom-out"), None, Action::ZoomOut), MenuItem::Button(fl!("zoom-reset"), None, Action::ZoomReset),
MenuItem::Divider, MenuItem::Button(fl!("zoom-out"), None, Action::ZoomOut),
MenuItem::Button(fl!("next-tab"), None, Action::TabNext), MenuItem::Divider,
MenuItem::Button(fl!("previous-tab"), None, Action::TabPrev), MenuItem::Button(fl!("next-tab"), None, Action::TabNext),
MenuItem::Divider, MenuItem::Button(fl!("previous-tab"), None, Action::TabPrev),
MenuItem::Button(fl!("split-horizontal"), None, Action::PaneSplitHorizontal), MenuItem::Divider,
MenuItem::Button(fl!("split-vertical"), None, Action::PaneSplitVertical), MenuItem::Button(
MenuItem::Button( fl!("split-horizontal"),
fl!("pane-toggle-maximize"), None,
None, Action::PaneSplitHorizontal,
Action::PaneToggleMaximized, ),
), MenuItem::Button(fl!("split-vertical"), None, Action::PaneSplitVertical),
MenuItem::Divider, MenuItem::Button(
MenuItem::Button( fl!("pane-toggle-maximize"),
fl!("menu-color-schemes"), None,
None, Action::PaneToggleMaximized,
Action::ColorSchemes(config.color_scheme_kind()), ),
), MenuItem::Divider,
MenuItem::Button(fl!("menu-settings"), None, Action::Settings), MenuItem::Button(
MenuItem::Divider, fl!("menu-color-schemes"),
MenuItem::Button(fl!("menu-about"), None, Action::About), None,
], Action::ColorSchemes(config.color_scheme_kind()),
), ),
), MenuItem::Button(fl!("menu-settings"), None, Action::Settings),
]) MenuItem::Divider,
.item_height(ItemHeight::Dynamic(40)) MenuItem::Button(fl!("menu-about"), None, Action::About),
.item_width(ItemWidth::Uniform(240)) ],
.spacing(4.0) ),
.into() ],
)
} }