On Thu, 2008-12-25 at 12:24 +0100, Thomas Steinacher wrote:

in all the discussions on IRC, it always eluded me that you were using
ClutterGroup as a base class - my bad.

> I am trying to implement something I call Sizer.  A Sizer can be
> attached to my subclass of ClutterGroup which I call SizedGroup. It
> has a method "update" in which size and position of the children of
> the SizedGroup is updated. I am overriding the "add" virtual function
> to call sizer.update() when a child is added to my SizedGroup.

short answer is: don't.

ClutterGroup is a fixed layout manager, and every subclass overriding
the ::allocate virtual function will inevitably conflict with the
default implementation because of the necessary chaining up to update
the allocation inside ClutterActor.

what you want is perfectly achievable by subclassing ClutterActor - and
implementing a ClutterContainer, if you wish to use the Container
methods, even though it's fairly easy to add those by yourself.

when adding a new child to a container you must call the
queue_relayout() method on the container itself:

  # simple container with only one child
  def add (self, child):
      self._child = child
      self.queue_relayout()

inside the ::allocate implementation of the container, you must call
clutter_actor_allocate() on each child:

  # simple allocation
  def do_allocate (self, box, origin_changed):
      # chain up
      clutter.Actor.do_allocate(self, box, origin_changed)

      # allocate the same size we got, unless it's smaller than
      # the minimum requested size of the child, in which case
      # we allocate that
      alloc_width  = box.x2 - box.x1
      alloc_height = box.y2 - box.y1
      min_width, min_height, natural_width, natural_height = 
self._child.get_preferred_size()
      if min_width > alloc_width:
          alloc_width = min_width
      if min_height > alloc_height:
          alloc_height = min_height

      self._child.allocate(clutter.ActorBox(0, 0, alloc_width, alloc_height), 
origin_changed)

> I am not calling allocate on the children in my SizedGroup because I
> would like to be able to switch the sizer of a SizedGroup dynamically
> using an animation (there could be a grid sizer, random sizer etc.),
> and I am not sure if that can be done using allocate.

what you want is a "pluggable" layout manager, an object the defines the
allocation policy on a container actor. inside the ::allocate
implementation you ask the layout manager object to compute the new
allocation depending on animations, ad hoc rules, etc., like:

  # base class for layout manager, allocating as much as the container
  # is given
  class LayoutManager:
      def get_allocation (self, box, child):
          return clutter.ActorBox(0, 0, box.x2 - box.x1, box.y2 - box.y1)

  # another layout manager, allocating as much as the child requests,
  # similar to the ClutterGroup policy
  class FillLayoutManager (LayoutManager):
      def get_allocation (self, box, child):
          (m_w, m_h, n_w, n_h) = child.get_preferred_size()
          return clutter.ActorBox(0, 0, n_w, n_h)

  # inside the container actor
  def do_allocate (self, box, origin_changed):
      clutter.Actor.do_allocate(self, box, origin_changed)

      allocation = self._layout_manager.get_allocation(box, self._child)
      self._child.allocate(allocation, origin_changed)

  def set_layout_manager (self, manager=None):
      if manager is None:
          self._layout_manager = LayoutManager()
      else:
          self._layout_manager = manager

[NOTE: all this code is untested and should be regarded as pseudo-code
strikingly similar to Python]

trying to force all of this on a ClutterGroup is never going to work.

ciao,
 Emmanuele.

-- 
Emmanuele Bassi, Intel Open Source Technology Center

-- 
To unsubscribe send a mail to [email protected]

Reply via email to