beeware / toga

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

SplitContainer does not honor content ratio #2882

Open PiGo86 opened 2 weeks ago

PiGo86 commented 2 weeks ago

Describe the bug

I tried to implement a 1/3 - 2/3 UI with SplitContainer, by running this code inspired by the Toga documentation:

import toga
from toga.style.pack import COLUMN, Pack

class Tutorial2App(toga.App):

    def startup(self):
        data = [("root%s" % i, "value %s" % i) for i in range(1, 100)]

        left_container = toga.Table(headings=["Hello", "World"], data=data)

        right_content = toga.Box(style=Pack(direction=COLUMN, padding_top=50))

        for b in range(0, 10):
            right_content.add(
                toga.Button(
                    "Hello world %s" % b,
                    style=Pack(width=200, padding=20),
                )
            )

        right_container = toga.ScrollContainer(horizontal=False)

        right_container.content = right_content

        split = toga.SplitContainer()

        # The content of the split container can be specified as a simple list:
        #    split.content = [left_container, right_container]
        # but you can also specify "weight" with each content item, which will
        # set an initial size of the columns to make a "heavy" column wider than
        # a narrower one. In this example, the right container will be twice
        # as wide as the left one.
        split.content = [(left_container, 1), (right_container, 2)]

        self.main_window = toga.MainWindow()
        self.main_window.content = split
        self.main_window.show()

def main():
    return Tutorial2App("Tutorial 2", "org.beeware.toga.tutorial")

if __name__ == "__main__":
    main().main_loop()

As a result, I get a 1/2 - 1/2 ratio (see screenshot)

Steps to reproduce

Run the code above

Expected behavior

Getting a 1/3 - 2/3 ratio

Screenshots

Capture d’écran du 2024-10-05 17-00-19

Environment

Logs

Additional context

No response

freakboy3742 commented 2 weeks ago

Thanks for the report.

It looks like the issue is related to setting the split proportion before the widget is visible. Due to a quirk of how GTK renders, we can't apply the split proportion at the time the content is defined - we need to wait until the widget is rendered, and the apply the split proportion. However, when this is done on a widget that hasn't been rendered yet, the set_bounds() operation that would apply the split occurs when the widget's size is "1x1"... which is ignored, because GTK's split position is based on actual pixels, not a proportion.

My guess is that there's a missing invocation to set_bounds() because the widget is the "top level" widget in the layout - but more investigation is required.