fyne-io / fyne-x

Community extensions to the cross platform GUI in Go based on Material Design
Other
235 stars 59 forks source link

Two State ToolbarAction Widget #92

Open jimorc opened 1 week ago

jimorc commented 1 week ago

There is the occasional need for a ToolbarAction widget that changes its displayed icon each time the widget is tapped. Here are two examples where this would be useful:

  1. In a media application where when a media file is being played, the theme.MediaPauseIcon or theme.MediaStopIcon would be displayed, and when no media file is being played, the theme.MediaPlayIcon would be displayed.
  2. In an app with multiple panels that may be open or closed, display, for example, the left panel open or left panel closed icon as appropriate.

Those are the two specific use cases that I see for my current app. No doubt there will be others.

Is it possible to construct a solution with the existing APIs?

Not a good one. I see two possible solutions:

  1. In the activation handler for the ToolbarAction, change the icon. This is unsatisfactory because it moves GUI code to an app's business logic.
  2. Use two separate ToolbarAction widgets, one for each icon. Unfortunately, ToolbarActions can neither be hidden nor disabled, so if the user taps the wrong widget, they will be left to determine why no action was taken.

There is another potential solution, but that would require adding functionality to ToolbarItems to be hidden, shown, disabled, enabled, and so forth. I assume that this functionality was not provided for a good reason.

I have coded the widget along with a demo program. This is available in the twostate branch at https://github.com/jimorc/fyne-x/tree/twostate. If it is agreed that this widget would be useful, I will add more tests, additional documentation, and then do a PR.

andydotxyz commented 1 week ago

There is a third option (which I guess is what you implemented) to just create an object that has the ToolbarObject() method. It's not strictly speaking a widget with just that, so how it is used or made available may be non-obvious but I'm sure something like this could be useful.

If the change is conveying some sort of state then it makes sense as an addition, if it is literally just changing the Icon each time tapped then 1. may be more desirable - there is no requirement that the callback from a widget go directly to business logic - the button would often be an inline function that calls out to business logic with appropriate parameters.