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()