Hi Julien,

I tried to translate examplebox.c into Python. See attached file, if it
can help you...

Damien.


Le Mon, 23 Feb 2009 15:47:21 +0100,
Julien Pauty <[email protected]> a écrit :

> Hello,
> 
> I'm trying to implement a container in python.
> 
> I have something like this:
> 
> class Cont(clutter.Actor, clutter.Container):
> 
>     __gtype_name__ = 'Cont'
> 
>     def __init__(self):
>         clutter.Actor.__init__(self)
>         clutter.Container.__init__(self)
> 
> 
>     def do_add(self, child):
>         clutter.Container.do_add(self, child)
> 
>     def do_remove(self, child):
>         clutter.Container.do_remove(child)
> 
> If try to build such a class I get the following error:
> 
>    clutter.Container.__init__(self)
> NotImplementedError: Cont can not be constructed
> 
> I tried to provide some dummy method for the container, but this seems
> useless, since Container provides default implementations.
> 
> I also tried to not call the __init__ method of container, which seems
> logical, since it's an interface. However, I get the following error
> when I call do_add:.
> 
>  Warning: g_type_interface_peek: assertion `instance_class != NULL'
> failed clutter.Container.do_add(self, child)
> 
> This sounds like something is not initialized, but what ?
> 
> So, what is the regular way to implement an interface ?
> 
> Thanks,
> 
> Julien
#!/usr/bin/env python
# -*- coding: utf-8 -*

import pygtk
pygtk.require('2.0')
import gobject
import clutter

class ExampleBox(clutter.Actor, clutter.Container):
    """
    Simple example of a container actor.
 
    ExampleBox imposes a specific layout on its children, 
    unlike clutter.Group which is a free-form container.
 
    Specifically, ExampleBox lays out its children along an imaginary
    horizontal line.
    """
    
    def __init__(self):
        clutter.Actor.__init__(self)
        self.set_property('request-mode', clutter.REQUEST_WIDTH_FOR_HEIGHT)
        self.children = list()
    
    def do_add(self, actor):
        self.pack(actor)
    
    def do_remove(self, actor):
        for child in self.children:
            if child == actor:
                child.unparent()
                self.children.remove(child)
                self.emit('actor-removed', actor)
                self.queue_relayout()
                break
    
    def foreach(self, callback, user_data):
        for child in self.children:
            callback(child, user_data)
    
    def show_all(self):
        for child in self.children:
            child.show()
        self.show()
    
    def hide_all(self):
        self.hide()
        for child in self.children:
            child.hide()
    
    def do_paint(self):
        for child in self.children:
            child.paint()
    
    def do_pick(self, color):
        for child in self.children:
            child.pick(color)
    
    def do_get_preferred_width(self, for_height):
        """
        For this container, the preferred width is the sum of the widths
        of the children. The preferred width depends on the height provided
        by for_height.
        """

        min_width = 0
        natural_width = 0

        # Calculate the preferred width for this container, 
        # based on the preferred width requested by the children:
        for child in self.children:
            if child.get_property('visible'):
                child_min_width, child_natural_width = \
                                          child.get_preferred_width(for_height)
                min_width += child_min_width
                natural_width += child_natural_width
        return min_width, natural_width
    
    def do_get_preferred_height(self, for_width):
        """
        For this container, the preferred height is the maximum height
        of the children. The preferred height is independent of the given
        width.
        """
        
        min_height = 0
        natural_height = 0
        
        # Calculate the preferred height for this container, 
        # based on the preferred height requested by the children:
        for child in self.children:
            if child.get_property('visible'):
                child_min_height, child_natural_height = \
                                          child.get_preferred_height(for_width)
                min_height += child_min_height
                natural_height += child_natural_height
        return min_height, natural_height
    
    def do_allocate(self, box, absolute_origin_changed):
        # Look at each child actor:
        child_x = 0
        for child in self.children:
            # Discover what size the child wants:
            min_width, min_height, natural_width, natural_height = \
                                                     child.get_preferred_size()
            
            # Calculate the position and size that the child may actually have:
            
            # Position the child just after the previous child, horizontally:
            child_box = clutter.ActorBox()
            child_box.x1 = child_x
            child_box.x2 = child_x + natural_width
            child_x = child_box.x2
            
            # Position the child at the top of the container:
            child_box.y1 = 0
            child_box.y2 = child_box.y1 + natural_height
            
            # Tell the child what position and size it may actually have:
            child.allocate(child_box, absolute_origin_changed)
            #print child_box.x1, child_box.x2, child_box.y1, child_box.y2
        clutter.Actor.allocate(self, box, absolute_origin_changed)
    
    def destroy(self):
        # Destroy each child actor when this container is destroyed:
        for child in self.children:
            child.destroy()
        del self.children
        self.children = list()
        clutter.Actor.destroy(self)
    
    #
    # # Public API
    #
    def pack(self, actor):
        """
        Packs the given actor into ExampleBox instance.
        
        :Parameters:
          actor : clutter.Actor
            An Actor object to pack into the box.
        """
        self.children.append(actor)
        actor.set_parent(self)
        
        # queue a relayout of the container
        self.queue_relayout()
    
    def remove_all(self):
        """
        Removes all child actors for the ExampleBox instance.
        """
        for child in tuple(self.children):
            self.remove(child)
gobject.type_register(ExampleBox)


if __name__ == '__main__':
    import os
    print os.getpid()
    stage_color = clutter.Color(0x00, 0x00, 0x00, 0xff)
    actor_color = clutter.Color(0xff, 0xff, 0xff, 0x99)
    actor_color2 = clutter.Color(0x10, 0x40, 0x90, 0xff)
    
    stage = clutter.Stage()
    stage.set_size(200, 200)
    stage.set_color(stage_color)
    
    box = ExampleBox()
    box.set_size(-1, -1)
    box.set_position(20, 20)
    stage.add(box)
    box.show()
    
    actor = clutter.Rectangle(actor_color)
    actor.set_size(75, 75)
    box.add(actor)
    actor.show()
    
    actor2 = clutter.Rectangle(actor_color2)
    actor2.set_size(75, 75)
    box.add(actor2)
    actor2.show()
    
    stage.show()
    clutter.main()

Reply via email to