menu_bar: add min_width/max_width constraints and update examples
This commit is contained in:
parent
6158af1991
commit
7903ee12c0
7 changed files with 191 additions and 55 deletions
|
|
@ -236,26 +236,26 @@ impl cosmic::Application for App {
|
|||
(
|
||||
"hi 1".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 12", None, Action::Hi),
|
||||
menu::Item::Button("hi 13", None, Action::Hi2),
|
||||
menu::Item::button("hi 12", None, Action::Hi),
|
||||
menu::Item::button("hi 13", None, Action::Hi2),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hi 2".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 21", None, Action::Hi),
|
||||
menu::Item::Button("hi 22", None, Action::Hi2),
|
||||
menu::Item::Folder(
|
||||
menu::Item::button("hi 21", None, Action::Hi),
|
||||
menu::Item::button("hi 22", None, Action::Hi2),
|
||||
menu::Item::folder(
|
||||
"nest 3 2 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("21", None, Action::Hi),
|
||||
menu::Item::Button("242", None, Action::Hi2),
|
||||
menu::Item::Button("2443", None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
menu::Item::button("21", None, Action::Hi),
|
||||
menu::Item::button("242", None, Action::Hi2),
|
||||
menu::Item::button("2443", None, Action::Hi3),
|
||||
menu::Item::folder(
|
||||
"nest 4 2 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("243", None, Action::Hi2),
|
||||
menu::Item::Button("2444", None, Action::Hi),
|
||||
menu::Item::button("243", None, Action::Hi2),
|
||||
menu::Item::button("2444", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
@ -265,34 +265,34 @@ impl cosmic::Application for App {
|
|||
(
|
||||
"hi 3".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 31", None, Action::Hi),
|
||||
menu::Item::Button("hi 332", None, Action::Hi2),
|
||||
menu::Item::Button("hi 3333", None, Action::Hi3),
|
||||
menu::Item::Button("hi 33334", None, Action::Hi3),
|
||||
menu::Item::Button("hi 333335", None, Action::Hi3),
|
||||
menu::Item::Button("hi 3333336", None, Action::Hi3),
|
||||
menu::Item::button("hi 31", None, Action::Hi),
|
||||
menu::Item::button("hi 332", None, Action::Hi2),
|
||||
menu::Item::button("hi 3333", None, Action::Hi3),
|
||||
menu::Item::button("hi 33334", None, Action::Hi3),
|
||||
menu::Item::button("hi 333335", None, Action::Hi3),
|
||||
menu::Item::button("hi 3333336", None, Action::Hi3),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hiiiiiiiiiiiiiiiiiii 4".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 4", None, Action::Hi),
|
||||
menu::Item::Button("hi 44", None, Action::Hi2),
|
||||
menu::Item::Button("hi 444", None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
menu::Item::button("hi 4", None, Action::Hi),
|
||||
menu::Item::button("hi 44", None, Action::Hi2),
|
||||
menu::Item::button("hi 444", None, Action::Hi3),
|
||||
menu::Item::folder(
|
||||
"nest 4 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 41", None, Action::Hi),
|
||||
menu::Item::Button("hi 442", None, Action::Hi2),
|
||||
menu::Item::Folder(
|
||||
menu::Item::button("hi 41", None, Action::Hi),
|
||||
menu::Item::button("hi 442", None, Action::Hi2),
|
||||
menu::Item::folder(
|
||||
"nest 3 4 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 443", None, Action::Hi2),
|
||||
menu::Item::Button("hi 4444", None, Action::Hi),
|
||||
menu::Item::Button("hi 44444", None, Action::Hi3),
|
||||
menu::Item::Button("hi 444445", None, Action::Hi3),
|
||||
menu::Item::Button("hi 4444446", None, Action::Hi3),
|
||||
menu::Item::Button("hi 44444447", None, Action::Hi3),
|
||||
menu::Item::button("hi 443", None, Action::Hi2),
|
||||
menu::Item::button("hi 4444", None, Action::Hi),
|
||||
menu::Item::button("hi 44444", None, Action::Hi3),
|
||||
menu::Item::button("hi 444445", None, Action::Hi3),
|
||||
menu::Item::button("hi 4444446", None, Action::Hi3),
|
||||
menu::Item::button("hi 44444447", None, Action::Hi3),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -122,19 +122,21 @@ impl App {
|
|||
Some(menu::items(
|
||||
&HashMap::new(),
|
||||
vec![
|
||||
menu::Item::Button("New window", None, ContextMenuAction::WindowNew),
|
||||
menu::Item::Divider,
|
||||
menu::Item::Folder(
|
||||
menu::Item::button("New window", None, ContextMenuAction::WindowNew),
|
||||
menu::Item::divider(),
|
||||
menu::Item::folder(
|
||||
"View",
|
||||
vec![menu::Item::CheckBox(
|
||||
vec![menu::Item::checkbox(
|
||||
"Hide content",
|
||||
None,
|
||||
self.hide_content,
|
||||
ContextMenuAction::ToggleHideContent,
|
||||
)],
|
||||
),
|
||||
menu::Item::Divider,
|
||||
menu::Item::Button("Quit", None, ContextMenuAction::WindowClose),
|
||||
)
|
||||
.width(200)
|
||||
.min_width(180),
|
||||
menu::Item::divider(),
|
||||
menu::Item::button("Quit", None, ContextMenuAction::WindowClose),
|
||||
],
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,23 +160,26 @@ pub fn menu_bar<'a>(config: &Config, key_binds: &HashMap<KeyBind, Action>) -> El
|
|||
menu::items(
|
||||
key_binds,
|
||||
vec![
|
||||
menu::Item::Button(
|
||||
menu::Item::button(
|
||||
"New window",
|
||||
Some(cosmic::widget::icon::from_name("screenshot-window-symbolic").into()),
|
||||
Action::WindowNew,
|
||||
),
|
||||
menu::Item::Divider,
|
||||
menu::Item::Folder(
|
||||
menu::Item::divider(),
|
||||
menu::Item::folder(
|
||||
"View",
|
||||
vec![menu::Item::CheckBox(
|
||||
vec![menu::Item::checkbox(
|
||||
"Hide content",
|
||||
Some(cosmic::widget::icon::from_name("view-conceal-symbolic").into()),
|
||||
config.hide_content,
|
||||
Action::ToggleHideContent,
|
||||
)],
|
||||
),
|
||||
menu::Item::Divider,
|
||||
menu::Item::Button(
|
||||
)
|
||||
.width(280)
|
||||
.min_width(200)
|
||||
.max_width(300),
|
||||
menu::Item::divider(),
|
||||
menu::Item::button(
|
||||
"Quit",
|
||||
Some(cosmic::widget::icon::from_name("window-close-symbolic").into()),
|
||||
Action::WindowClose,
|
||||
|
|
|
|||
|
|
@ -135,9 +135,9 @@ impl cosmic::Application for App {
|
|||
Some(menu::items(
|
||||
&HashMap::new(),
|
||||
vec![
|
||||
menu::Item::Button("Move Up", None, NavMenuAction::MoveUp(id)),
|
||||
menu::Item::Button("Move Down", None, NavMenuAction::MoveDown(id)),
|
||||
menu::Item::Button("Delete", None, NavMenuAction::Delete(id)),
|
||||
menu::Item::button("Move Up", None, NavMenuAction::MoveUp(id)),
|
||||
menu::Item::button("Move Down", None, NavMenuAction::MoveDown(id)),
|
||||
menu::Item::button("Delete", None, NavMenuAction::Delete(id)),
|
||||
],
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ impl cosmic::Application for App {
|
|||
.item_context(move |item| {
|
||||
Some(widget::menu::items(
|
||||
&HashMap::new(),
|
||||
vec![widget::menu::Item::Button(
|
||||
vec![widget::menu::Item::button(
|
||||
format!("Action on {}", item.name.to_string()),
|
||||
None,
|
||||
Action::None,
|
||||
|
|
@ -227,7 +227,7 @@ impl cosmic::Application for App {
|
|||
.item_context(|item| {
|
||||
Some(widget::menu::items(
|
||||
&HashMap::new(),
|
||||
vec![widget::menu::Item::Button(
|
||||
vec![widget::menu::Item::button(
|
||||
format!("Action on {}", item.name),
|
||||
None,
|
||||
Action::None,
|
||||
|
|
@ -238,12 +238,12 @@ impl cosmic::Application for App {
|
|||
Some(widget::menu::items(
|
||||
&HashMap::new(),
|
||||
vec![
|
||||
widget::menu::Item::Button(
|
||||
widget::menu::Item::button(
|
||||
format!("Action on {} category", category.to_string()),
|
||||
None,
|
||||
Action::None,
|
||||
),
|
||||
widget::menu::Item::Button(
|
||||
widget::menu::Item::button(
|
||||
format!("Other action on {} category", category.to_string()),
|
||||
None,
|
||||
Action::None,
|
||||
|
|
|
|||
|
|
@ -1647,7 +1647,12 @@ fn get_children_layout<Message>(
|
|||
) -> (Size, Vec<f32>, Vec<Size>) {
|
||||
let width = match item_width {
|
||||
ItemWidth::Uniform(u) => f32::from(u),
|
||||
ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)),
|
||||
ItemWidth::Static(s) => {
|
||||
let base = f32::from(menu_tree.width.unwrap_or(s));
|
||||
let min = menu_tree.min_width.map(f32::from).unwrap_or(0.0);
|
||||
let max = menu_tree.max_width.map(f32::from).unwrap_or(f32::MAX);
|
||||
base.clamp(min, max)
|
||||
}
|
||||
};
|
||||
|
||||
let child_sizes: Vec<Size> = match item_height {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ pub struct MenuTree<Message> {
|
|||
pub(crate) children: Vec<MenuTree<Message>>,
|
||||
/// The width of the menu tree
|
||||
pub(crate) width: Option<u16>,
|
||||
/// The min width of the menu tree
|
||||
pub(crate) min_width: Option<u16>,
|
||||
/// The max width of the menu tree
|
||||
pub(crate) max_width: Option<u16>,
|
||||
/// The height of the menu tree
|
||||
pub(crate) height: Option<u16>,
|
||||
}
|
||||
|
|
@ -48,6 +52,8 @@ impl<Message: Clone + 'static> MenuTree<Message> {
|
|||
item: item.into(),
|
||||
children: Vec::new(),
|
||||
width: None,
|
||||
min_width: None,
|
||||
max_width: None,
|
||||
height: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +68,8 @@ impl<Message: Clone + 'static> MenuTree<Message> {
|
|||
item: item.into(),
|
||||
children: children.into_iter().map(Into::into).collect(),
|
||||
width: None,
|
||||
min_width: None,
|
||||
max_width: None,
|
||||
height: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +84,18 @@ impl<Message: Clone + 'static> MenuTree<Message> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the min width of the menu tree.
|
||||
pub fn min_width(mut self, min: u16) -> Self {
|
||||
self.min_width = Some(min);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the max width of the menu tree.
|
||||
pub fn max_width(mut self, max: u16) -> Self {
|
||||
self.max_width = Some(max);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the height of the menu tree.
|
||||
/// See [`ItemHeight`]
|
||||
///
|
||||
|
|
@ -170,19 +190,66 @@ pub enum MenuItemKind<A: MenuAction, L: Into<Cow<'static, str>>> {
|
|||
Divider,
|
||||
}
|
||||
|
||||
/// A menu item with optional width configuration.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use cosmic::widget::menu;
|
||||
///
|
||||
/// // Simple button
|
||||
/// menu::Item::button("Save", None, Action::Save);
|
||||
///
|
||||
/// // Button with icon
|
||||
/// menu::Item::button(
|
||||
/// "Open",
|
||||
/// Some(cosmic::widget::icon::from_name("document-open-symbolic").into()),
|
||||
/// Action::Open,
|
||||
/// );
|
||||
///
|
||||
/// // Checkbox
|
||||
/// menu::Item::checkbox("Show Hidden", None, true, Action::ToggleHidden);
|
||||
///
|
||||
/// // Folder with custom width
|
||||
/// menu::Item::folder("Recent", vec![
|
||||
/// menu::Item::button("file1.txt", None, Action::OpenRecent(0)),
|
||||
/// ]).width(300);
|
||||
///
|
||||
/// // Divider
|
||||
/// menu::Item::divider();
|
||||
///
|
||||
/// // Folder with custom width constraints
|
||||
/// menu::Item::folder("Recent", vec![
|
||||
/// menu::Item::button("file1.txt", None, Action::OpenRecent(0)),
|
||||
/// ]).width(300).min_width(200).max_width(400);
|
||||
///
|
||||
/// // Using min_width to ensure a minimum size
|
||||
/// menu::Item::button("Short", None, Action::Short).min_width(150);
|
||||
///
|
||||
/// // Using max_width to cap the size
|
||||
/// menu::Item::button("Very Long Label Here", None, Action::Long).max_width(200);
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
/// A menu item with optional width configuration
|
||||
pub struct MenuItem<A: MenuAction, L: Into<Cow<'static, str>>> {
|
||||
/// Kind of menu item.
|
||||
kind: MenuItemKind<A, L>,
|
||||
/// Optional width override for this item's submenu.
|
||||
/// Optional width override for this item.
|
||||
width: Option<u16>,
|
||||
/// Optional min width for this item.
|
||||
min_width: Option<u16>,
|
||||
/// Optional max width for this item.
|
||||
max_width: Option<u16>,
|
||||
}
|
||||
|
||||
impl<A: MenuAction, L: Into<Cow<'static, str>>> MenuItem<A, L> {
|
||||
/// Create from a kind with no width set
|
||||
pub fn new(kind: MenuItemKind<A, L>) -> Self {
|
||||
Self { kind, width: None }
|
||||
Self {
|
||||
kind,
|
||||
width: None,
|
||||
min_width: None,
|
||||
max_width: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder method to set width
|
||||
|
|
@ -191,22 +258,39 @@ impl<A: MenuAction, L: Into<Cow<'static, str>>> MenuItem<A, L> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Builder method to set minimum width
|
||||
pub fn min_width(mut self, min: u16) -> Self {
|
||||
self.min_width = Some(min);
|
||||
self
|
||||
}
|
||||
|
||||
/// Builder method to set max width
|
||||
pub fn max_width(mut self, max: u16) -> Self {
|
||||
self.max_width = Some(max);
|
||||
self
|
||||
}
|
||||
|
||||
/// Create a button menu item.
|
||||
pub fn button(label: L, icon: Option<icon::Handle>, action: A) -> Self {
|
||||
Self::new(MenuItemKind::Button(label, icon, action))
|
||||
}
|
||||
|
||||
/// Create a disabled button menu item.
|
||||
pub fn button_disabled(label: L, icon: Option<icon::Handle>, action: A) -> Self {
|
||||
Self::new(MenuItemKind::ButtonDisabled(label, icon, action))
|
||||
}
|
||||
|
||||
/// Create a checkbox menu item.
|
||||
pub fn checkbox(label: L, icon: Option<icon::Handle>, checked: bool, action: A) -> Self {
|
||||
Self::new(MenuItemKind::CheckBox(label, icon, checked, action))
|
||||
}
|
||||
|
||||
/// Create a folder (submenu) menu item.
|
||||
pub fn folder(label: L, children: Vec<MenuItem<A, L>>) -> Self {
|
||||
Self::new(MenuItemKind::Folder(label, children))
|
||||
}
|
||||
|
||||
/// Create a divider between menu items.
|
||||
pub fn divider() -> Self {
|
||||
Self::new(MenuItemKind::Divider)
|
||||
}
|
||||
|
|
@ -283,6 +367,8 @@ pub fn menu_items<
|
|||
let mut trees = vec![];
|
||||
let spacing = crate::theme::spacing();
|
||||
let item_width = item.width;
|
||||
let item_min_width = item.min_width;
|
||||
let item_max_width = item.max_width;
|
||||
|
||||
match item.kind {
|
||||
MenuItemKind::Button(label, icon, action) => {
|
||||
|
|
@ -308,6 +394,14 @@ pub fn menu_items<
|
|||
tree = tree.width(width);
|
||||
}
|
||||
|
||||
if let Some(min_width) = item_min_width {
|
||||
tree = tree.min_width(min_width);
|
||||
}
|
||||
|
||||
if let Some(max_width) = item_max_width {
|
||||
tree = tree.max_width(max_width);
|
||||
}
|
||||
|
||||
trees.push(tree);
|
||||
}
|
||||
MenuItemKind::ButtonDisabled(label, icon, action) => {
|
||||
|
|
@ -334,6 +428,14 @@ pub fn menu_items<
|
|||
tree = tree.width(width);
|
||||
}
|
||||
|
||||
if let Some(min_width) = item_min_width {
|
||||
tree = tree.min_width(min_width);
|
||||
}
|
||||
|
||||
if let Some(max_width) = item_max_width {
|
||||
tree = tree.max_width(max_width);
|
||||
}
|
||||
|
||||
trees.push(tree);
|
||||
}
|
||||
MenuItemKind::CheckBox(label, icon, value, action) => {
|
||||
|
|
@ -372,6 +474,14 @@ pub fn menu_items<
|
|||
tree = tree.width(width);
|
||||
}
|
||||
|
||||
if let Some(min_width) = item_min_width {
|
||||
tree = tree.min_width(min_width);
|
||||
}
|
||||
|
||||
if let Some(max_width) = item_max_width {
|
||||
tree = tree.max_width(max_width);
|
||||
}
|
||||
|
||||
trees.push(tree);
|
||||
}
|
||||
MenuItemKind::Folder(label, children) => {
|
||||
|
|
@ -405,6 +515,14 @@ pub fn menu_items<
|
|||
tree = tree.width(width);
|
||||
}
|
||||
|
||||
if let Some(min_width) = item_min_width {
|
||||
tree = tree.min_width(min_width);
|
||||
}
|
||||
|
||||
if let Some(max_width) = item_max_width {
|
||||
tree = tree.max_width(max_width);
|
||||
}
|
||||
|
||||
trees.push(tree);
|
||||
}
|
||||
MenuItemKind::Divider => {
|
||||
|
|
@ -417,6 +535,14 @@ pub fn menu_items<
|
|||
tree = tree.width(width);
|
||||
}
|
||||
|
||||
if let Some(min_width) = item_min_width {
|
||||
tree = tree.min_width(min_width);
|
||||
}
|
||||
|
||||
if let Some(max_width) = item_max_width {
|
||||
tree = tree.max_width(max_width);
|
||||
}
|
||||
|
||||
trees.push(tree);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue