beeware / toga

A Python native, OS native GUI toolkit.
https://toga.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
4.35k stars 671 forks source link

Make Command properties dynamically updatable #2700

Open mhsmith opened 4 months ago

mhsmith commented 4 months ago

Discussed in https://github.com/beeware/toga/discussions/2691

Originally posted by @rontarrant


Hey, there, all, I've been playing around with the example in section 4.1.4 of the Toga docs. Just for fun, I decided to have the Action 4 toolbar button change the text in the Action 3 toolbar button.

Here are my modifications:

def action4(widget):
    if cmd3.text == "Action 3":
        cmd3.text = "Non-action"
    else:
        cmd3.text = "Action 3"

    cmd3.enabled = not cmd3.enabled

However, the text on Action 3 didn't change. I threw in a print() statement to make sure the change was actually taking place (and it was) but the only way to see the change in the toolbar button was to remove the entire toolbar and put it back... which—of course—causes the UI to 'jump.'

Question: Is there a way to change the text that's more straightforward? Like, is there a way to access the toolbar button's text directly instead of through the Command object?

Likewise for the Menu item.

mhsmith commented 4 months ago

Originally posted by @freakboy3742


I think this is likely in the space between a feature and a bug. It's a bug in as much as it seems obvious that you should be able to change labels; it's a request for a new feature on the basis that nothing in the docs says that this behavior should be possible.

When you remove then re-add the toolbar, you're forcing a refresh; hence, the new labels are applied. You'd likely find that you'd have the same effect if you added or removed a single item to the toolbar. This is because there is a listener in place on changes to the toolbar, which causes the whole toolbar to be recreated.

So - the simplest "fix" for this would be to modify the property for the command label to trigger an update on any command set it is a part of. The complication here is that the command doesn't know what command sets it is part of.

A better fix would be to connect changes in the command label to the refreshing underlying command implementation, which should give you access to the underlying native menu and toolbar items. This would allow the labels for those items to be updated directly.

mhsmith commented 4 months ago

This applies not just to text, but also to all the other properties which don't have a @property method, such as tooltip and group.

It also applies to icon, because even though it is a @property, the setter doesn't pass the value to the implementation layer.

rontarrant commented 4 months ago

Thanks for putting this in your 'TODO' list. 👍

freakboy3742 commented 4 months ago

@rontarrant To set expectations: yes, this is on our "TODO" in the sense that we've recognised the issue as something we'd like to see addressed - but that doesn't mean it's going to be addressed in the near future.

Toga (and the whole of BeeWare) is an Open Source project. The only way to guarantee that something will be fixed is to fix it yourself. We can't provide any guarantees that a someone else will implement a feature, or the timeline on which that will occur. All I can tell you is that this specific issue isn't likely to be on my personal radar for at least 6 months, if not longer.

If this is an issue that impacts you, then I'd encourage you to make an attempt at fixing it. We're happy to provide any assistance or pointers to get you started, and we'll review any contributions that are made (merging once they pass review).

rontarrant commented 1 month ago

Noted, @freakboy3742 . I've got my hands full already, but I'll add it to my list of things I might get to sometime down the road... if I get some free time. For now, I'll use PySide6 for my current projects. Deadlines, you know.