feat: responsive menu

This commit is contained in:
Ashley Wulber 2025-04-16 13:07:03 -04:00 committed by Michael Murphy
parent 1c2c859eac
commit 9336731c7d
4 changed files with 1028 additions and 272 deletions

1026
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,7 @@ features = ["syntect", "vi"]
[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

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::surface;
use cosmic::widget::menu::action::MenuAction; use cosmic::widget::menu::action::MenuAction;
use cosmic::widget::menu::key_bind::KeyBind; use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::widget::segmented_button::Entity; use cosmic::widget::segmented_button::Entity;
@ -389,6 +390,7 @@ pub enum Message {
SaveAsResult(segmented_button::Entity, DialogResult), SaveAsResult(segmented_button::Entity, DialogResult),
Scroll(f32), Scroll(f32),
SelectAll, SelectAll,
Surface(surface::Action),
SystemThemeModeChange(cosmic_theme::ThemeMode), SystemThemeModeChange(cosmic_theme::ThemeMode),
SyntaxTheme(usize, bool), SyntaxTheme(usize, bool),
TabActivate(segmented_button::Entity), TabActivate(segmented_button::Entity),
@ -2444,6 +2446,11 @@ impl Application for App {
}); });
} }
} }
Message::Surface(a) => {
return cosmic::task::message(cosmic::Action::Cosmic(
cosmic::app::Action::Surface(a),
));
}
Message::SystemThemeModeChange(_theme_mode) => { Message::SystemThemeModeChange(_theme_mode) => {
return self.update_config(); return self.update_config();
} }
@ -2757,6 +2764,7 @@ impl Application for App {
fn header_start(&self) -> Vec<Element<Message>> { fn header_start(&self) -> Vec<Element<Message>> {
vec![menu_bar( vec![menu_bar(
&self.core,
&self.config, &self.config,
&self.config_state, &self.config_state,
&self.key_binds, &self.key_binds,

View file

@ -3,19 +3,23 @@
use cosmic::widget::menu::key_bind::KeyBind; use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::widget::menu::{items as menu_items, root as menu_root, Item as MenuItem}; use cosmic::widget::menu::{items as menu_items, root as menu_root, Item as MenuItem};
use cosmic::{ use cosmic::{
app::Core,
iced::{widget::column, Background, Length}, iced::{widget::column, Background, Length},
iced_core::Border, iced_core::Border,
widget::{ widget::{
self, divider, horizontal_space, self, divider, horizontal_space,
menu::{menu_button, ItemHeight, ItemWidth, MenuBar, Tree as MenuTree}, menu::{menu_button, ItemHeight, ItemWidth, MenuBar, Tree as MenuTree},
segmented_button, responsive_menu_bar, segmented_button,
}, },
Element, Element,
}; };
use std::{collections::HashMap, path::PathBuf}; use std::{collections::HashMap, path::PathBuf, sync::LazyLock};
use crate::{fl, Action, Config, ConfigState, Message}; use crate::{fl, Action, Config, ConfigState, 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>(
key_binds: &HashMap<KeyBind, Action>, key_binds: &HashMap<KeyBind, Action>,
entity: segmented_button::Entity, entity: segmented_button::Entity,
@ -67,6 +71,7 @@ pub fn context_menu<'a>(
} }
pub fn menu_bar<'a>( pub fn menu_bar<'a>(
core: &Core,
config: &Config, config: &Config,
config_state: &ConfigState, config_state: &ConfigState,
key_binds: &HashMap<KeyBind, Action>, key_binds: &HashMap<KeyBind, Action>,
@ -119,133 +124,130 @@ pub fn menu_bar<'a>(
)); ));
} }
MenuBar::new(vec![ responsive_menu_bar()
MenuTree::with_children( .item_height(ItemHeight::Dynamic(40))
menu_root(fl!("file")), .item_width(ItemWidth::Uniform(320))
menu_items( .spacing(4.0)
key_binds, .into_element(
vec![ core,
MenuItem::Button(fl!("new-file"), None, Action::NewFile), key_binds,
MenuItem::Button(fl!("new-window"), None, Action::NewWindow), MENU_ID.clone(),
MenuItem::Divider, Message::Surface,
MenuItem::Button(fl!("open-file"), None, Action::OpenFileDialog), vec![
MenuItem::Folder(fl!("open-recent-file"), recent_files), (
MenuItem::Button(fl!("close-file"), None, Action::CloseFile), (fl!("file")),
MenuItem::Divider, vec![
MenuItem::Button(fl!("menu-open-project"), None, Action::OpenProjectDialog), MenuItem::Button(fl!("new-file"), None, Action::NewFile),
MenuItem::Folder(fl!("open-recent-project"), recent_projects), MenuItem::Button(fl!("new-window"), None, Action::NewWindow),
MenuItem::Folder(fl!("close-project"), close_projects), MenuItem::Divider,
MenuItem::Divider, MenuItem::Button(fl!("open-file"), None, Action::OpenFileDialog),
MenuItem::Button(fl!("save"), None, Action::Save), MenuItem::Folder(fl!("open-recent-file"), recent_files),
MenuItem::Button(fl!("save-as"), None, Action::SaveAsDialog), MenuItem::Button(fl!("close-file"), None, Action::CloseFile),
MenuItem::Divider, MenuItem::Divider,
MenuItem::Button(fl!("revert-all-changes"), None, Action::RevertAllChanges), MenuItem::Button(fl!("menu-open-project"), None, Action::OpenProjectDialog),
MenuItem::Divider, MenuItem::Folder(fl!("open-recent-project"), recent_projects),
MenuItem::Button( MenuItem::Folder(fl!("close-project"), close_projects),
fl!("menu-document-statistics"), MenuItem::Divider,
None, MenuItem::Button(fl!("save"), None, Action::Save),
Action::ToggleDocumentStatistics, MenuItem::Button(fl!("save-as"), None, Action::SaveAsDialog),
), MenuItem::Divider,
//TODO MenuItem::Button(fl!("document-type"), Action::Todo), MenuItem::Button(fl!("revert-all-changes"), None, Action::RevertAllChanges),
//TODO MenuItem::Button(fl!("encoding"), Action::Todo), MenuItem::Divider,
MenuItem::Button( MenuItem::Button(
fl!("menu-git-management"), fl!("menu-document-statistics"),
None, None,
Action::ToggleGitManagement, Action::ToggleDocumentStatistics,
), ),
//TODO MenuItem::Button(fl!("print"), Action::Todo), //TODO MenuItem::Button(fl!("document-type"), Action::Todo),
MenuItem::Divider, //TODO MenuItem::Button(fl!("encoding"), Action::Todo),
MenuItem::Button(fl!("quit"), None, Action::Quit), MenuItem::Button(
], fl!("menu-git-management"),
), None,
), Action::ToggleGitManagement,
MenuTree::with_children( ),
menu_root(fl!("edit")), //TODO MenuItem::Button(fl!("print"), Action::Todo),
menu_items( MenuItem::Divider,
key_binds, MenuItem::Button(fl!("quit"), None, Action::Quit),
vec![ ],
MenuItem::Button(fl!("undo"), None, Action::Undo), ),
MenuItem::Button(fl!("redo"), None, Action::Redo), (
MenuItem::Divider, (fl!("edit")),
MenuItem::Button(fl!("cut"), None, Action::Cut), vec![
MenuItem::Button(fl!("copy"), None, Action::Copy), MenuItem::Button(fl!("undo"), None, Action::Undo),
MenuItem::Button(fl!("paste"), None, Action::Paste), MenuItem::Button(fl!("redo"), None, Action::Redo),
MenuItem::Button(fl!("select-all"), None, Action::SelectAll), MenuItem::Divider,
MenuItem::Divider, MenuItem::Button(fl!("cut"), None, Action::Cut),
MenuItem::Button(fl!("find"), None, Action::Find), MenuItem::Button(fl!("copy"), None, Action::Copy),
MenuItem::Button(fl!("replace"), None, Action::FindAndReplace), MenuItem::Button(fl!("paste"), None, Action::Paste),
MenuItem::Button(fl!("find-in-project"), None, Action::ToggleProjectSearch), MenuItem::Button(fl!("select-all"), None, Action::SelectAll),
/*TODO: implement spell-check MenuItem::Divider,
MenuItem::Divider, MenuItem::Button(fl!("find"), None, Action::Find),
MenuItem::Button(fl!("spell-check"), None, Action::Todo), MenuItem::Button(fl!("replace"), None, Action::FindAndReplace),
*/ MenuItem::Button(fl!("find-in-project"), None, Action::ToggleProjectSearch),
], /*TODO: implement spell-check
), MenuItem::Divider,
), MenuItem::Button(fl!("spell-check"), None, Action::Todo),
MenuTree::with_children( */
menu_root(fl!("view")), ],
menu_items( ),
key_binds, (
vec![ (fl!("view")),
MenuItem::Folder( vec![
fl!("indentation"), MenuItem::Folder(
vec![ fl!("indentation"),
MenuItem::CheckBox( vec![
fl!("automatic-indentation"), MenuItem::CheckBox(
None, fl!("automatic-indentation"),
config.auto_indent, None,
Action::ToggleAutoIndent, config.auto_indent,
), Action::ToggleAutoIndent,
MenuItem::Divider, ),
menu_tab_width(1), MenuItem::Divider,
menu_tab_width(2), menu_tab_width(1),
menu_tab_width(3), menu_tab_width(2),
menu_tab_width(4), menu_tab_width(3),
menu_tab_width(5), menu_tab_width(4),
menu_tab_width(6), menu_tab_width(5),
menu_tab_width(7), menu_tab_width(6),
menu_tab_width(8), menu_tab_width(7),
//TODO MenuItem::Divider, menu_tab_width(8),
//TODO MenuItem::Button(fl!("convert-indentation-to-spaces"), Action::Todo), //TODO MenuItem::Divider,
//TODO MenuItem::Button(fl!("convert-indentation-to-tabs"), Action::Todo), //TODO MenuItem::Button(fl!("convert-indentation-to-spaces"), Action::Todo),
], //TODO MenuItem::Button(fl!("convert-indentation-to-tabs"), Action::Todo),
), ],
MenuItem::Divider, ),
MenuItem::Button(fl!("zoom-in"), None, Action::ZoomIn), MenuItem::Divider,
MenuItem::Button(fl!("default-size"), None, Action::ZoomReset), MenuItem::Button(fl!("zoom-in"), None, Action::ZoomIn),
MenuItem::Button(fl!("zoom-out"), None, Action::ZoomOut), MenuItem::Button(fl!("default-size"), None, Action::ZoomReset),
MenuItem::Divider, MenuItem::Button(fl!("zoom-out"), None, Action::ZoomOut),
MenuItem::CheckBox( MenuItem::Divider,
fl!("word-wrap"), MenuItem::CheckBox(
None, fl!("word-wrap"),
config.word_wrap, None,
Action::ToggleWordWrap, config.word_wrap,
), Action::ToggleWordWrap,
MenuItem::CheckBox( ),
fl!("show-line-numbers"), MenuItem::CheckBox(
None, fl!("show-line-numbers"),
config.line_numbers, None,
Action::ToggleLineNumbers, config.line_numbers,
), Action::ToggleLineNumbers,
MenuItem::CheckBox( ),
fl!("highlight-current-line"), MenuItem::CheckBox(
None, fl!("highlight-current-line"),
config.highlight_current_line, None,
Action::ToggleHighlightCurrentLine, config.highlight_current_line,
), Action::ToggleHighlightCurrentLine,
//TODO: MenuItem::CheckBox(fl!("syntax-highlighting"), Action::Todo), ),
MenuItem::Divider, //TODO: MenuItem::CheckBox(fl!("syntax-highlighting"), Action::Todo),
MenuItem::Button(fl!("menu-settings"), None, Action::ToggleSettingsPage), MenuItem::Divider,
//TODO MenuItem::Divider, MenuItem::Button(fl!("menu-settings"), None, Action::ToggleSettingsPage),
//TODO MenuItem::Button(fl!("menu-keyboard-shortcuts"), Action::Todo), //TODO MenuItem::Divider,
MenuItem::Divider, //TODO MenuItem::Button(fl!("menu-keyboard-shortcuts"), Action::Todo),
MenuItem::Button(fl!("menu-about"), None, Action::About), MenuItem::Divider,
], MenuItem::Button(fl!("menu-about"), None, Action::About),
), ],
), ),
]) ],
.item_height(ItemHeight::Dynamic(40)) )
.item_width(ItemWidth::Uniform(320))
.spacing(4.0)
.into()
} }