Skip to content

Conversation

npwoods
Copy link
Contributor

@npwoods npwoods commented Aug 3, 2025

This is an initial attempt to support menus with checkmarks. This initial support has the following caveats:

  • It doesn't work :-). It isn't clear to me how the state on MenuItem objects get sync'd with MenuEntry objects. I expected this to be happening within MenuFromItemTree::update_shadow_tree(), but that seems to not happen in practice. By contrast, enabled gets sync'd just fine.
  • The graphics for non-muda checkmarks is almost certainly insufficient. I anticipate strong opinions about what this should look like
  • muda seems to have distinct structs for menu items that support icons versus checkmarks. It isn't clear to me why this would be. This means that icons and checkmarks cannot be used at the same time when muda is used.
  • muda has some odd default behaviors for CheckMenuItem, like automatically toggling the checkmark. This behavior will likely need to be suppressed.

Separately, I would also like to see accelerator support; I do see key_sequence commented out in builtin_structs.rs. I'm sure that some of the guidance rectifying the above issues will translate for accelerator support.

This is an initial attempt to support menus with checkmarks.  This initial support has the following caveats:
- It doesn't work :-).  It isn't clear to me how the state on `MenuItem` objects get sync'd with `MenuEntry` objects.  I expected this to be happening within `MenuFromItemTree::update_shadow_tree()`, but that seems to not happen in practice.  By contrast, `enabled` gets sync'd just fine.
- The graphics for non-muda checkmarks is almost certainly insufficient.  I anticipate strong opinions about what this should look like
- `muda` seems to have distinct structs for menu items that support icons versus checkmarks.  It isn't clear to me why this would be.  This means that icons and checkmarks cannot be used at the same time when `muda` is used.
- `muda` has some odd default behaviors for `CheckMenuItem`, like automatically toggling the checkmark.  This behavior will likely need to be suppressed.

Separately, I would also like to see accelerator support; I do see `key_sequence` commented out in `builtin_structs.rs`.  I'm sure that some of the guidance rectifying the above issues will translate for accelerator support.
@ogoffart
Copy link
Member

ogoffart commented Aug 4, 2025

Thanks for the contributions.

Note that we would need both a checked and checkable flag.

It isn't clear to me how the state on MenuItem objects get sync'd with MenuEntry objects.

Depending if the menu has if or for, it is done in update_shadow_tree, or here:

for prop in ["title", "enabled"] {

muda seems to have distinct structs for menu items that support icons versus checkmarks. It isn't clear to me why this would be. This means that icons and checkmarks cannot be used at the same time when muda is used.

Then priority to check mark.
It may be either a limitation of muda, or the way it is in some platform API.

Separately, I would also like to see accelerator support

Some work for that has started (eg in #8906)

npwoods and others added 3 commits August 4, 2025 21:35
- Handling `checkable` and `checked` when copying into `MenuEntry`
- Changing `muda` code to honor `checkable` and give it priority over `icon`
@ogoffart
Copy link
Member

Is it ready to be reviewed?

@npwoods
Copy link
Contributor Author

npwoods commented Aug 14, 2025

It's ready with the caveats acknowledged in the original PR. I think you provided feedback that allowed me to ddress the first and third.

@npwoods
Copy link
Contributor Author

npwoods commented Aug 14, 2025

The only definite problem I'm aware about is the last problem; muda (at least on Windows) seems to unilaterally decide to toggle checkmarks on checked menu items

Relevant code on Windows: https://github.com/tauri-apps/muda/blob/ff2cecc76b69b54ed253fd526320f9c50ddb6236/src/platform_impl/windows/mod.rs#L1193

It isn't clear to me why muda does this. I suspect that you guys might have stronger opinions on what should be done here.

@ogoffart
Copy link
Member

I made a change in #9159 that is causing conflict but should simplify the implementation a bit

@npwoods
Copy link
Contributor Author

npwoods commented Aug 15, 2025

Merged!

@ogoffart
Copy link
Member

Thanks!

Could you please add documentation in contextmenuarea.mdx.

Also maybe have a checkable entry in the gallery as an example.

The only definite problem I'm aware about is the last problem; muda (at least on Windows) seems to unilaterally decide to toggle checkmarks on checked menu items

I'm not exactly sure what behavior we want here.
I see a few option:

  1. Do the same as in muda in our code: make checked an in-out property and let people do binding like this
   some-item := MenuItem {
       title: "Check me";
       checkable: true;
   } 

   // ... elsewhere, use the property in a binding or something
   background: some-item.checked ? blue : red;
  1. Don't automatically change the checkable as you implemented. User would be expected to do a activated => { self.checked = !self.checked } themselves (and can potentially add more checking code)

I'm tempted do go with the option 1. I think we should change the value of checked automaticallty (This can be done in MenuFromItemTree::activate, I'd say.)

1.  Adding documentation to `contextmenuarea.mdx`
2.  Adding logic to toggle checkmarks
Copy link
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Could you also add a tests?
Prehaps you can extend this test
https://github.com/slint-ui/slint/blob/master/tests/cases/widgets/menubar.slint

and this one
https://github.com/slint-ui/slint/blob/master/tests/cases/widgets/contextmenu.slint

to include a checkable menu and checked that the property is correctly updated.

@npwoods
Copy link
Contributor Author

npwoods commented Aug 16, 2025

I've created two new test cases, but it isn't clear to me how these test cases are executed (the code behind seems to just be comments in the Slint code; presumably there is a test harness?)

Also in the logic that actually does the toggling, I query for the status of the checkable/checked properties with a method called get_internal(). This does not look like the proper solution; I defer to you

@ogoffart
Copy link
Member

it isn't clear to me how these test cases are executed

There are test driver that run these. See https://github.com/slint-ui/slint/blob/master/docs/testing.md#driver-tests

with a method called get_internal()

Indeed that's not good. You need to get a Pin. You can do that with
menu_item.as_pin_ref().checkable() or something like that.

@npwoods
Copy link
Contributor Author

npwoods commented Aug 20, 2025

Are there any more outstanding issues related to this PR?

@ogoffart
Copy link
Member

Sorry for the delay.

This is looking good.
The menubar c++ test is failing. Please edit the cpp part of the test with the same thing as rust.

Also please add a entry to the gallery's menu

Copy link
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Member

@tronical tronical left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API looks good to me, too.

@ogoffart ogoffart merged commit 19d8350 into slint-ui:master Aug 21, 2025
38 checks passed
{
if let Some(menu_item) = menu_item.downcast::<MenuItem>() {
if menu_item.as_pin_ref().checkable() {
menu_item.checked.set(!menu_item.as_pin_ref().checked());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I suspect this is what I’m looking for?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants