2

I try to create a proper container Class for Gtk in Python (MyBin in the code below). There seems to be no authoritative documentation on how to do that, only bits and pieces, which I glued together with trial and error. – There are many open questions, but let me focus on size_allocate() here:

What is the the original size_allocate() function doing? And what is my overlaid version in my container class supposed to do?

I already do 95% know that I have to replace the original method with my own by prepending “do_” to form the do_size_allocate() method (by trial and error – see code below; I could not find anything talking about all those “do_*” functions).

I found so far, that calling self.set_allocation(allocation) seems to be a good idea as is self.get_child().size_allocate(...) to give the child some working space (see code). – Any other obligations I have to fulfill? What is the original function doing additionally?

Regarding the allocation I pass down to the child: I need to adapt it (not in the code below yet). I successfully(?) used a fresh Gdk.Rectangle() on which I set x, y, width and height, but I somehow feel that it’s wrong and something with (do_)adjust_size_allocation() should be used instead. But how?

Lets look into the documentation of do_size_allocate():

This function is only used by Gtk.Container subclasses, to assign a size and position to their child widgets. [“Only used”? Only called from? Only implemented at? Only overwritten by? – Well, I’m doing it already, but the doc wasn’t helpful in finding out how.]

In this function, the allocation may be adjusted. [How?] It will be forced to a 1x1 minimum size [Can confirm only that get_allocation() will return a 1x1 if I don’t set anything.],and the adjust_size_allocation virtual method on the child will be used to adjust the allocation. [What? For my own allocation? Or for the one I set on the child via ...get_child().size_allocate()? Who calls that adjust method? In which conditions is it not called before size_allocate()?] Standard adjustments include removing the widget’s margins, and applying the widget’s Gtk.Widget :halign and Gtk.Widget :valign properties.

#!/usr/bin/python3

import gi

gi.require_version('Gtk', '3.0')

from gi.repository import Gtk

class MyBin(Gtk.Bin):
    def __init__(self):
        super().__init__()

    def do_size_allocate(self, allocation):
        print('PARENT METHOD do_size_allocate', allocation.width)
        # if not called, `get_allocation()` in `do_draw()` will return a 1x1 rectangle
        self.set_allocation(allocation)
        # strangely required so that `do_draw()` will be called even on this class!
        self.get_child().size_allocate(allocation)

    def do_draw(self, c):
        allocation = self.get_allocation()
        print('PARENT do_draw()', allocation.width)
        self.propagate_draw(self.get_child(), c)

class MyChild(Gtk.Button):
    def __init__(self):
        super().__init__()
        self.connect('size-allocate', self.size_allocate_handler)
        self.connect('draw', self.draw_handler)

    def size_allocate_handler(self, self2, allocation):
        print('CHILD signal size-allocate', allocation.width)

    def draw_handler(self, self2, c):
        allocation = self.get_allocation()
        print('CHILD signal draw', allocation.width)

class MainWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title='d2see test pattern')
        the_child = MyChild()
        my_container = MyBin()
        my_container.add(the_child)
        self.add(my_container)
        self.show_all()

if __name__ == '__main__':
    MainWindow()
    Gtk.main()
Robert Siemer
  • 32,405
  • 11
  • 84
  • 94
  • 1
    One thing you can do in the meanwhile (I don't have the answer, sorry) is look at the GTK source code. For example, here is [the implementation for `GtkBin`](https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/gtkbin.c#L294) under GTK 3.24 (GTK 4 no longer has containers). – BobMorane Dec 06 '22 at 12:25
  • @BobMorane Very good pointer! – Robert Siemer Dec 06 '22 at 16:36

0 Answers0