improv: icon support for menus

This commit is contained in:
Eduardo Flores 2024-11-18 12:49:33 +01:00 committed by Ashley Wulber
parent a355a049d9
commit e7b9c6493a
2 changed files with 65 additions and 36 deletions

View file

@ -159,18 +159,27 @@ pub fn menu_bar<'a>(config: &Config, key_binds: &HashMap<KeyBind, Action>) -> El
menu::items( menu::items(
key_binds, key_binds,
vec![ vec![
menu::Item::Button("New window", Action::WindowNew), menu::Item::Button(
"New window",
Some(cosmic::widget::icon::from_name("screenshot-window-symbolic").into()),
Action::WindowNew,
),
menu::Item::Divider, menu::Item::Divider,
menu::Item::Folder( menu::Item::Folder(
"View", "View",
vec![menu::Item::CheckBox( vec![menu::Item::CheckBox(
"Hide content", "Hide content",
Some(cosmic::widget::icon::from_name("view-conceal-symbolic").into()),
config.hide_content, config.hide_content,
Action::ToggleHideContent, Action::ToggleHideContent,
)], )],
), ),
menu::Item::Divider, menu::Item::Divider,
menu::Item::Button("Quit", Action::WindowClose), menu::Item::Button(
"Quit",
Some(cosmic::widget::icon::from_name("window-close-symbolic").into()),
Action::WindowClose,
),
], ],
), ),
)]) )])

View file

@ -9,6 +9,7 @@ use std::rc::Rc;
use iced_widget::core::{renderer, Element}; use iced_widget::core::{renderer, Element};
use crate::iced_core::{Alignment, Length}; use crate::iced_core::{Alignment, Length};
use crate::widget::icon;
use crate::widget::menu::action::MenuAction; use crate::widget::menu::action::MenuAction;
use crate::widget::menu::key_bind::KeyBind; use crate::widget::menu::key_bind::KeyBind;
use crate::{theme, widget}; use crate::{theme, widget};
@ -171,11 +172,11 @@ pub fn menu_button<'a, Message: 'a>(
/// - `Divider` - Represents a divider between menu items. /// - `Divider` - Represents a divider between menu items.
pub enum MenuItem<A: MenuAction, L: Into<Cow<'static, str>>> { pub enum MenuItem<A: MenuAction, L: Into<Cow<'static, str>>> {
/// Represents a button menu item. /// Represents a button menu item.
Button(L, A), Button(L, Option<icon::Handle>, A),
/// Represents a button menu item that is disabled. /// Represents a button menu item that is disabled.
ButtonDisabled(L, A), ButtonDisabled(L, Option<icon::Handle>, A),
/// Represents a checkbox menu item. /// Represents a checkbox menu item.
CheckBox(L, bool, A), CheckBox(L, Option<icon::Handle>, bool, A),
/// Represents a folder menu item. /// Represents a folder menu item.
Folder(L, Vec<MenuItem<A, L>>), Folder(L, Vec<MenuItem<A, L>>),
/// Represents a divider between menu items. /// Represents a divider between menu items.
@ -240,53 +241,72 @@ where
.enumerate() .enumerate()
.flat_map(|(i, item)| { .flat_map(|(i, item)| {
let mut trees = vec![]; let mut trees = vec![];
let spacing = crate::theme::active().cosmic().spacing;
match item { match item {
MenuItem::Button(label, action) => { MenuItem::Button(label, icon, action) => {
let key = find_key(&action, key_binds); let key = find_key(&action, key_binds);
let menu_button = menu_button(vec![ let mut items = vec![
widget::text(label).into(), widget::text(label).into(),
widget::horizontal_space().width(Length::Fill).into(), widget::horizontal_space().width(Length::Fill).into(),
widget::text(key).into(), widget::text(key).into(),
]) ];
.on_press(action.message());
if let Some(icon) = icon {
items.insert(0, widget::icon::icon(icon).size(16).into());
items.insert(1, widget::Space::with_width(spacing.space_xxs).into());
}
let menu_button = menu_button(items).on_press(action.message());
trees.push(MenuTree::<Message, Renderer>::new(menu_button)); trees.push(MenuTree::<Message, Renderer>::new(menu_button));
} }
MenuItem::ButtonDisabled(label, action) => { MenuItem::ButtonDisabled(label, icon, action) => {
let key = find_key(&action, key_binds); let key = find_key(&action, key_binds);
let menu_button = menu_button(vec![
let mut items = vec![
widget::text(label).into(), widget::text(label).into(),
widget::horizontal_space().width(Length::Fill).into(), widget::horizontal_space().width(Length::Fill).into(),
widget::text(key).into(), widget::text(key).into(),
]); ];
if let Some(icon) = icon {
items.insert(0, widget::icon::icon(icon).size(16).into());
items.insert(1, widget::Space::with_width(spacing.space_xxs).into());
}
let menu_button = menu_button(items);
trees.push(MenuTree::<Message, Renderer>::new(menu_button)); trees.push(MenuTree::<Message, Renderer>::new(menu_button));
} }
MenuItem::CheckBox(label, value, action) => { MenuItem::CheckBox(label, icon, value, action) => {
let key = find_key(&action, key_binds); let key = find_key(&action, key_binds);
trees.push(MenuTree::new( let mut items = vec![
menu_button(vec![ if value {
if value { widget::icon::from_name("object-select-symbolic")
widget::icon::from_name("object-select-symbolic") .size(16)
.size(16) .icon()
.icon() .class(theme::Svg::Custom(Rc::new(|theme| {
.class(theme::Svg::Custom(Rc::new(|theme| { iced_widget::svg::Style {
iced_widget::svg::Style { color: Some(theme.cosmic().accent_color().into()),
color: Some(theme.cosmic().accent_color().into()), }
} })))
}))) .width(Length::Fixed(16.0))
.width(Length::Fixed(16.0)) .into()
.into() } else {
} else { widget::Space::with_width(Length::Fixed(16.0)).into()
widget::Space::with_width(Length::Fixed(16.0)).into() },
}, widget::Space::with_width(spacing.space_xxs).into(),
widget::Space::with_width(Length::Fixed(8.0)).into(), widget::text(label).align_x(iced::Alignment::Start).into(),
widget::text(label).align_x(iced::Alignment::Start).into(), widget::horizontal_space().width(Length::Fill).into(),
widget::horizontal_space().width(Length::Fill).into(), widget::text(key).into(),
widget::text(key).into(), ];
])
.on_press(action.message()), if let Some(icon) = icon {
)); items.insert(1, widget::icon::icon(icon).size(16).into());
}
trees.push(MenuTree::new(menu_button(items).on_press(action.message())));
} }
MenuItem::Folder(label, children) => { MenuItem::Folder(label, children) => {
trees.push(MenuTree::<Message, Renderer>::with_children( trees.push(MenuTree::<Message, Renderer>::with_children(