Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to disable ToolbarActions #2306 #4347

Merged
merged 12 commits into from
Feb 1, 2024

Conversation

dominikhauk
Copy link
Contributor

@dominikhauk dominikhauk commented Oct 28, 2023

Description:

Added ability to disable ToolbarActions.
I chose to embed the button directly, since it already handles the disable-state logic.
Also, since the button is returned as a pointer, no separate refreshing logic is required. This seems to have been an issue with previous PRs for this issue.

Please let me know if the "Since:" comment with version 2.5 is fine, or if you prefer another version.

I don't necessarily like that the state of Icon & OnActivated are now essentially duplicated (once in the ToolbarAction and once in the underlying Button itself), but I did not want to break backward compatibility by changing the public interface. Let me know what your thoughts are on this.

Fixes #2306

I have tested the code using the following addition to the fyne-demo (cmd/fyne_demo/tutorials/widget.go):

func makeToolbarTab(_ fyne.Window) fyne.CanvasObject {
	paste := widget.NewToolbarAction(theme.ContentPasteIcon(), func() { fmt.Println("Paste") })

	t := widget.NewToolbar(widget.NewToolbarAction(theme.MailComposeIcon(), func() { fmt.Println("New") }),
		widget.NewToolbarSeparator(),
		widget.NewToolbarSpacer(),
		widget.NewToolbarAction(theme.ConfirmIcon(), func() {
			if paste.Disabled() {
				paste.Enable()
			} else {
				paste.Disable()
			}
		}),
		widget.NewToolbarSpacer(),
		widget.NewToolbarAction(theme.ContentCutIcon(), func() { fmt.Println("Cut") }),
		widget.NewToolbarAction(theme.ContentCopyIcon(), func() { fmt.Println("Copy") }),
		paste,
	)

	return container.NewBorder(t, nil, nil, nil)
}

Checklist:

  • Tests included.
  • Lint and formatter run with no errors.
  • Tests all pass.

Where applicable:

  • Public APIs match existing style and have Since: line.

Sorry, something went wrong.

@dominikhauk dominikhauk marked this pull request as ready for review October 28, 2023 11:45
@dominikhauk
Copy link
Contributor Author

I also experience some weird rendering behavior in the fyne_demo after making my changes. After a refresh, the alignment of the toolbar items seems to be off. I am not sure if this a local bug for me, or if it is caused by my changes:

Before:
grafik

After refresh:
grafik

The code that I am using is

func makeToolbarTab(_ fyne.Window) fyne.CanvasObject {
	paste := widget.NewToolbarAction(theme.ContentPasteIcon(), func() { fmt.Println("Paste") })

	var t *widget.Toolbar

	t = widget.NewToolbar(widget.NewToolbarAction(theme.MailComposeIcon(), func() { fmt.Println("New") }),
		widget.NewToolbarSeparator(),
		widget.NewToolbarSpacer(),
		widget.NewToolbarAction(theme.ConfirmIcon(), func() {
			if paste.Disabled {
				paste.Disabled = false
			} else {
				paste.Disabled = true
			}
			t.Refresh()
		}),
		widget.NewToolbarSpacer(),
		widget.NewToolbarAction(theme.ContentCutIcon(), func() { fmt.Println("Cut") }),
		widget.NewToolbarAction(theme.ContentCopyIcon(), func() { fmt.Println("Copy") }),
		paste,
	)

	return container.NewBorder(t, nil, nil, nil)
}

Could you try it on your side and let me know if it happens as well on your machine?

@andydotxyz
Copy link
Member

Wasn't implementing the disablable interface desirable though? Maybe it isn't possible as the toolbar action is not really a widget?

@dominikhauk
Copy link
Contributor Author

Wasn't implementing the disablable interface desirable though? Maybe it isn't possible as the toolbar action is not really a widget?

I intentionally used the Disabled property, since this is also what the MenuItem in menu.go uses, and I wanted to stay consistent here.

I am not sure how you handled such situations in the past. Let me know if I should change the implementation, or how you want to continue.

@dominikhauk
Copy link
Contributor Author

By the way, what is the reasoning behind not making the toolbarItems widgets?
According to my current understanding, we would not be having these issues if the toolbarItems were normal widgets, right?
For example, a menuItem also is a widget:

widget.Base

@dominikhauk dominikhauk requested a review from dweymouth November 3, 2023 08:24
@coveralls
Copy link

coveralls commented Nov 7, 2023

Coverage Status

coverage: 64.629% (+0.004%) from 64.625%
when pulling 62610f6 on maruu:2306-disable-toolbar-actions
into 4f617dc on fyne-io:develop.

@dominikhauk dominikhauk force-pushed the 2306-disable-toolbar-actions branch from 0634bc7 to 4dc9db5 Compare November 8, 2023 12:07
@dominikhauk
Copy link
Contributor Author

Rebased branch to current develop state

@andydotxyz
Copy link
Member

By the way, what is the reasoning behind not making the toolbarItems widgets?

According to my current understanding, we would not be having these issues if the toolbarItems were normal widgets, right?

For example, a menuItem also is a widget:

widget.Base

It's about the public API. Internally menuItem is a widget, but the public api fyne.MenuItem is not. Using public APIs that are abstractions allows us to keep the widgets consistent.

A container will give the user control over its content through adding arbitrary widgets, but it is rare for a widget to do this. If you want a "toolbar that accepts anything" then wouldn't that just be a VBox with a background rectangle?

That said I don't know what the issue is here, the ToolbarObject returns a CanvasObject for its "implementation detail" and this can be a widget, disablable widget or anything else. So why would this be easier if the main object was a widget?

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

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

I can't quite see how the disabled item is refreshed without internal API access.
I try to give more detail inline - let me know if it is not clear.

@dominikhauk
Copy link
Contributor Author

Any idea why the tests are always failing with:

D:\a\fyne\setup-go-faster\go\1.17.13\x64\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\RUNNER~1\AppData\Local\Temp\go-link-3164744842\000008.o: in function `_cgo_preinit_init':
c:\go\src\runtime\cgo/gcc_libinit_windows.c:30: undefined reference to `__imp___iob_func'
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\RUNNER~1\AppData\Local\Temp\go-link-3164744842\000008.o: in function `x_cgo_sys_thread_create':
c:\go\src\runtime\cgo/gcc_libinit_windows.c:60: undefined reference to `__imp___iob_func'
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\RUNNER~1\AppData\Local\Temp\go-link-3164744842\000008.o: in function `x_cgo_notify_runtime_init_done':
c:\go\src\runtime\cgo/gcc_libinit_windows.c:101: undefined reference to `__imp___iob_func'
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\RUNNER~1\AppData\Local\Temp\go-link-3164744842\000009.o: in function `x_cgo_thread_start':
c:\go\src\runtime\cgo/gcc_util.c:18: undefined reference to `__imp___iob_func'
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\RUNNER~1\AppData\Local\Temp\go-link-3164744842\000010.o: in function `_cgo_sys_thread_start':
c:\go\src\runtime\cgo/gcc_windows_amd64.c:31: undefined reference to `__imp___iob_func'
collect2.exe: error: ld returned 1 exit status

? I don't see any connection to the code that I have changed.

@Jacalz
Copy link
Member

Jacalz commented Dec 2, 2023

@maruu It is not your fault. It’s a bug in versions of Go older than 1.20. We need to look at how we should address that on our next contributor meeting for Fyne.

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

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

More thoughts inline - good to have the feature working though.

@dominikhauk
Copy link
Contributor Author

Hi @andydotxyz @dweymouth, as discussed here: #4347 (comment) I changed the PR to now use the Button directly. The benefits from my point of view are that the state management is not duplicated, but can be reused from the Button itself.

I again tested the functionality with an extension of the fyne_demo app (see my initial PR description for the code if you want to give it a try). Let me know what you think.

@dominikhauk dominikhauk force-pushed the 2306-disable-toolbar-actions branch from 636deb5 to a701d5f Compare January 16, 2024 08:50
@dominikhauk
Copy link
Contributor Author

Rebased branch to current develop state

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

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

Looking good, but this will crash if you just create a &ToolbarAction{} directly as the constructor function is optional.

Since the ToolbarAction can also be created
without the constructor, the pointer to the
button could be nil.
@dominikhauk
Copy link
Contributor Author

Looking good, but this will crash if you just create a &ToolbarAction{} directly as the constructor function is optional.

You are totally correct. Since I cannot store a reference to the button directly (because it cannot be copied) I chose to use lazy initialization. I also added a test for this, hope that's okay. Let me know what you think.

Copy link
Member

@Jacalz Jacalz left a comment

Choose a reason for hiding this comment

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

Thanks for working on this. I have a few suggestions that will clean up the code a bit once resolved

@dominikhauk dominikhauk requested a review from Jacalz January 31, 2024 07:47
@Jacalz
Copy link
Member

Jacalz commented Feb 1, 2024

Please resolve the issues reported by the static analysis workflow

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

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

Well done and thanks, this is a great addition

@Jacalz Jacalz merged commit 34502cd into fyne-io:develop Feb 1, 2024
12 checks passed
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.

None yet

5 participants