fyne
fyne copied to clipboard
AssertRendersToMarkup does not invoke Canvas.EnsureMinSize
Checklist
- [X] I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
- [X] This issue only relates to a single bug. I will open new issues for any other problems.
Describe the bug
Unbinding a Label widget, setting its text value, and then rebinding the widget will yield the Label showing the size for the text value that was manually set, not the one set by the new binding.
How to reproduce
1: Bind the Label (which displays the bound text)
2: Undbind the Label and call Label.SetText("")
3: Bind the Label again to the same binding
This image shows the results of the first binding on the left and the second binding on the right.
Screenshots
No response
Example code
package fynebindingtest
import (
"testing"
"time"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/test"
"fyne.io/fyne/v2/widget"
)
func TestLabelRendering(t *testing.T) {
stringValue := "Domain1"
stringValueBinding := binding.NewString()
stringValueBinding.Set(stringValue)
label := widget.NewLabel("")
hBox := container.NewHBox(label)
time.Sleep(100 * time.Millisecond)
test.AssertObjectRendersToMarkup(t, "PriorToInitialBinding.xml", hBox)
label.Bind(stringValueBinding)
time.Sleep(100 * time.Millisecond)
test.AssertObjectRendersToMarkup(t, "AfterInitialBinding.xml", hBox)
label.Unbind()
label.SetText("")
time.Sleep(100 * time.Millisecond)
test.AssertObjectRendersToMarkup(t, "AfterUnbindingAndSettingTextToEmptyString.xml", hBox)
label.Bind(stringValueBinding)
time.Sleep(1000 * time.Millisecond)
test.AssertObjectRendersToMarkup(t, "AfterSecondBinding.xml", hBox)
label.Refresh()
time.Sleep(100 * time.Millisecond)
test.AssertObjectRendersToMarkup(t, "AfterSecondBindingAndLabelRefresh.xml", hBox)
}
Fyne version
current develop branch
Go compiler version
1.21.4
Operating system and version
Windows 10
Additional Information
No response
Upon further investigation, this issue has nothing to do with binding - you get the same results if you directly assign consecutive text values to the Label widget.
The problem here is that AssertObjectRendersToMarkup() does not invoke Canvas.EnsureMinSize because the canvas being used is not derived from common.Canvas. The consequence of this is that after the Label text is set back to the longer string, the Label widget size is never updated. So the issue is with the AssertObjectRendersToMarkup.
Subsequent investigation, deriving a headless canvas from common.Canvas and modifying the test code to use this canvas shows that this problem is resolved with that approach.
I spent quite a bit of time creating a headless application. It turned out to be very complicated. My approach was to create a headless canvas derived from common.Canvas, adding a renderedImage attribute which is the target of rendering the canvas.
Deriving from common.Canvas dragged in a huge number of dependencies, many of which derive from the Canvas.EnsureMinSize using cached data from prior renderings. I started by cloning the logic from the glfw version of Canvas, removing all the gl dependencies. This opened Pandora's box, as this introduced dependencies to many of the other files in the driver/glfw files, fir each of which I had to make a headless version, again removing gl dependencies. As I did this I realized I was creating a maintenance nightmare by copying all this logic. I also realized that most of the logic had nothing to do with gl. The proper way to do this would be to abstract all that logic into common/* files (in the same manner that common/canvas.go was created). Since I have neither the time or knowledge to do this efficiently, I abandoned the effort. The work in progress can be observed at https://github.com/pbrown12303/fyne under the develop branch.
Thanks for taking it this far @pbrown12303, hopefully someone can pick it up soon.