fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design
https://fyne.io/
Other
24.48k stars 1.36k forks source link

GridWrapLayout doesn't play nicely with parent containers/layouts #4852

Open Paul365x opened 3 months ago

Paul365x commented 3 months ago

Checklist

Describe the bug

When gridwraplayout initially runs, it gets a size of 0,0. This results, as noted in the docco, in a single column grid. Where there are a lot of items, the resulting initial min size has a very large height. While gridwraplayout modifies layout and minsize on subsequent runs, once the window is up and working and resized, parent containers/layouts continue to use the first very large height resulting in windows that go off the screen and are undraggable to resize and have a huge gap below the content. This has been tested with GridLayout containing GridWrapLayout. Sample code below. It is also affected by the size of the screen vs initial min height. The bug happens when the initial large height is greater than the screen real estate height.

How to reproduce

Run the example code with the number of displayed numbers large enough to push the content off the bottom of the screen before display.

Screenshots

image

Example code

package main

import (
    "image/color"
    "strconv"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/layout"
)

func main() {
    myApp := app.New()
    myWindow := myApp.NewWindow("Grid Wrap Layout")
    myWindow.Resize(fyne.NewSize(1800,300)) 

    grid := container.New(layout.NewGridWrapLayout(fyne.NewSize(50, 50)))
    for i := 0; i < 100; i++ {
        grid.Add(canvas.NewText(strconv.Itoa(i), color.Black))
    }

    myWindow.SetContent(
        container.New(
            layout.NewGridLayout(1),
            grid,
            layout.NewSpacer(),
        ),
    )

    //myWindow.Resize(fyne.NewSize(180, 75))
    myWindow.ShowAndRun()
}

Fyne version

2.4

Go compiler version

go version go1.22.2 linux/amd64

Operating system and version

Linux Mint 21.2 running Cinnamon/Gnome

Additional Information

No response

Jacalz commented 3 months ago

Two things to note:

Jacalz commented 3 months ago

Hmm. Another though, I wonder if it could be useful with some kind of alternative to .Add() but for adding like a slice or multiple items through a variadic input and then have a layout done afterwards?

Paul365x commented 3 months ago

thanks Jacalz

Two things to note:

If you don't need to do a layout on each loop iteration, you can probably modify the .Objects slice directly. If needed, you can call layout after that but in this example the content is laid out when showing the window so that should be fine.

I am not calling layout directly either in my test code or my application. I am not even sure where the flow of control goes after the show and run. I am a novice in both Golang and Fyne and this is my learning app.

You will see a lot better performance using widget.GridWrap that pools objects and only renders those in view. I will try that next time I get back to my code.

Paul365x commented 3 months ago

Hmm. Another though, I wonder if it could be useful with some kind of alternative to .Add() but for adding like a slice or multiple items through a variadic input and then have a layout done afterwards?

The reason for the add is that the real app - not the test code - lays out a color picker - a grid of clickable coloured circles used to select the background of an image. These colors are grouped into palettes of different amounts of colors.

andydotxyz commented 3 months ago

This seems to be a window manager specific issue. It is not allowing the window to become shorter after the initial hint is set. We've seen this on some Gnome versions too.

I'm not sure what to do here - it's part of the two-pass layout required similar to when text wraps.

andydotxyz commented 3 months ago

Hmm. Another though, I wonder if it could be useful with some kind of alternative to .Add() but for adding like a slice or multiple items through a variadic input and then have a layout done afterwards?

The reason for the add is that the real app - not the test code - lays out a color picker - a grid of clickable coloured circles used to select the background of an image. These colors are grouped into palettes of different amounts of colors.

Just checking - the colour picker in the dialog package was checked but you chose not to use it right?

Paul365x commented 3 months ago

It is very specific color picker in the real application. The use case is to match images to the color of t-shirts. As such there is a fixed palette for each print on demand site. This is going to be a multipurpose artwork manager. When we get to the next application - that of managing machine embroidery patterns - I may well want to use a more standard color picker.

Paul365x commented 3 months ago

I checked the test code against Gnome 45.2 with similar results. I am also getting similar results when putting a GridLayout in a GridLayout. Like Andy, not sure what to do next.

andydotxyz commented 3 months ago

It would be good to check on a different window manager codebase (KDE or LXDE etc) or non-Linux to check if this hunch is correct...

Paul365x commented 3 months ago

so I have tested this on a range of wm: lxde, openbox, kde etc. There are a variety of misbehaviours. I note that if the number of items is very large, the window might not render at all. But they all seem to result in windows that are not resizable vertically. I will not be doing macos or windows. Don't have the first and allergic to the second. So now going back to untrash my laptop

andydotxyz commented 3 months ago

For a very large number of items use the GridWrap widget instead of layout. The widgets are smarter because they can do serious caching to reduce what has to be rendered. Layouts are dumb in comparison and should only be used for arranging what should be visible.

andydotxyz commented 2 months ago

I think this may be a duplicate of #4888