2009/4/9 Emmanuele Bassi <[email protected]>

> On Thu, 2009-04-09 at 18:22 +0200, Julien Pauty wrote:
>
> > I'm using pyclutter. I have a container with a custom layout manager.
> > When I call raise_top on an actor contained in my container I get a
> > segfault. As I understand it I'm supposed to reimplement raise_child
> > in my class. However this method is never called. Digging a bit, I
> > found that CLUTTER_CONTAINER_GET_IFACE (container)->raise is NULL. I
> > suppose this means that somewhere an initiatilisation is not done.
> > Just to be sure, I also tried to implement a do_raise_child method,
> > but this is not called either.
> >
> > How can I get my python method called ?
>
>   def do_raise (container, child, sibling):
>      pass
>
> you should always look at the C API reference until pyclutter gets a
> proper one.


I tried with this method but it does not get called.

I join a minimal example showing the problem. On  my system, the raise_top
call makes the program crashing. Debugging show that the function pointer
"raise" of the interface is not initialized.

Cheer,

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):
        if actor in self.children:
    
            actor.unparent()
            self.children.remove(actor)
            self.emit('actor-removed', actor)
            self.queue_relayout()
                
    
    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.do_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)
        
    
    def do_raise(self, t, e):
        print "t1"
        
    def do_raise_actor(self, t, e):
        print "t2"
        
    def raise_actor(self, e, r):
        print "t3"

    def do_raise_child(self, t, e):
        print "t3"
        
    def raise_child(self, e, r):
        print "t4"


    
        
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()
    
    box.remove(actor2)
    box.remove(actor)
    
    box.add(actor2)
    box.add(actor)
    actor2.raise_top()
    stage.show()
    clutter.main()

Reply via email to