/* Updates the minimum number of rows and columns needed for layout */
static void _xfdashboard_scaled_table_layout_update_rows_and_columns(XfdashboardScaledTableLayout *self,
																		ClutterContainer *inContainer)
{
	XfdashboardScaledTableLayoutPrivate		*priv;
	ClutterRequestMode						requestMode;
	ClutterActorIter						iter;
	ClutterActor							*child;
	gint									numberChildren;
	gint									rows;
	gint									columns;

	g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self));
	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));
	g_return_if_fail(CLUTTER_IS_ACTOR(inContainer));

	priv=self->priv;

	/* Freeze notification */
	g_object_freeze_notify(G_OBJECT(self));

	/* Get number of visible child actors */
	numberChildren=0;
	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
	while(clutter_actor_iter_next(&iter, &child))
	{
		if(clutter_actor_is_visible(child)) numberChildren++;
	}

	if(numberChildren!=priv->numberChildren)
	{
		priv->numberChildren=numberChildren;
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_NUMBER_CHILDREN]);
	}

	/* Get request mode to determine if more rows than colums are needed
	 * or the opposite
	 */
	requestMode=clutter_actor_get_request_mode(CLUTTER_ACTOR(inContainer));

	/* Calculate and update number of rows and columns */
	if(requestMode==CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
	{
		rows=ceil(sqrt((double)priv->numberChildren));
		columns=ceil((double)priv->numberChildren / (double)priv->rows);
	}
		else
		{
			columns=ceil(sqrt((double)priv->numberChildren));
			rows=ceil((double)priv->numberChildren / (double)priv->columns);
		}

	if(rows!=priv->rows)
	{
		priv->rows=rows;
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_ROWS]);
	}

	if(columns!=priv->columns)
	{
		priv->columns=columns;
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_COLUMNS]);
	}

	/* Thaw notification */
	g_object_thaw_notify(G_OBJECT(self));
}
Exemplo n.º 2
0
/* snap size, as affected by resizing lower right corner,
 * will need extension if other corners are to be supported,
 * it seems possible to do all needed alignments through
 * simple workarounds when only snapping for lower right).
 */
static void snap_size (ClutterActor *actor,
                       gfloat        in_width,
                       gfloat        in_height,
                       gfloat       *out_width,
                       gfloat       *out_height)
{
  *out_width = in_width;
  *out_height = in_height;

  ClutterActor *parent;

  parent = clutter_actor_get_parent (actor);

  if (CLUTTER_IS_CONTAINER (parent))
    {
      gfloat in_x = clutter_actor_get_x (actor);
      gfloat in_y = clutter_actor_get_y (actor);
      gfloat in_end_x = in_x + in_width;
      gfloat in_end_y = in_y + in_height;


      gfloat best_x = 0;
      gfloat best_x_diff = 4096;
      gfloat best_y = 0;
      gfloat best_y_diff = 4096;
      GList *children, *c;
      children = clutter_container_get_children (CLUTTER_CONTAINER (parent));

      hor_pos = 0;
      ver_pos = 0;

      /* We only search our siblings for snapping...
       * perhaps we should search more.
       */

      for (c=children; c; c = c->next)
        {
          gfloat this_x = clutter_actor_get_x (c->data);
          gfloat this_width = clutter_actor_get_width (c->data);
          gfloat this_height = clutter_actor_get_height (c->data);
          gfloat this_end_x = this_x + this_width;
          gfloat this_y = clutter_actor_get_y (c->data);
          gfloat this_end_y = this_y + this_height;

          /* skip self */
          if (c->data == actor)
            continue;

/*
 end aligned with start
                    this_x     this_mid_x     this_end_x
in_x    in_mid_x    in_end_x
*/
          if (abs (this_x - in_end_x) < best_x_diff)
            {
              best_x_diff = abs (this_x - in_end_x);
              best_x = this_x;
              hor_pos=3;
            }
          if (abs (this_y - in_end_y) < best_y_diff)
            {
              best_y_diff = abs (this_y - in_end_y);
              best_y = this_y;
              ver_pos=3;
            }
/*
 ends aligned
                    this_x     this_mid_x     this_end_x
                          in_x    in_mid_x    in_end_x
*/
          if (abs (this_end_x - in_end_x) < best_x_diff)
            {
              best_x_diff = abs (this_end_x - in_end_x);
              best_x = this_end_x;
              hor_pos=3;
            }
          if (abs (this_end_y - in_end_y) < best_y_diff)
            {
              best_y_diff = abs (this_end_y - in_end_y);
              best_y = this_end_y;
              ver_pos=3;
            }
        }

        {
          if (best_x_diff < SNAP_THRESHOLD)
            {
              *out_width = best_x-in_x;
            }
          else
            {
              hor_pos = 0;
            }
          if (best_y_diff < SNAP_THRESHOLD)
            {
              *out_height = best_y-in_y;
            }
          else
            {
              ver_pos = 0;
            }
        }
    }
}
/* Re-layout and allocate children of container we manage */
static void _xfdashboard_scaled_table_layout_allocate(ClutterLayoutManager *self,
														ClutterContainer *inContainer,
														const ClutterActorBox *inAllocation,
														ClutterAllocationFlags inFlags)
{
	XfdashboardScaledTableLayoutPrivate		*priv;
	gint									row, col;
	ClutterActor							*child;
	ClutterActorIter						iter;
	gfloat									cellWidth, cellHeight;
	gfloat									childWidth, childHeight;
	gfloat									scaledChildWidth, scaledChildHeight;
	gfloat									largestWidth, largestHeight;
	gfloat									scaleWidth, scaleHeight;
	gfloat									aspectRatio;
	gfloat									x, y;
	ClutterActorBox							childAllocation;

	g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self));
	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));

	priv=XFDASHBOARD_SCALED_TABLE_LAYOUT(self)->priv;

	/* Get size of container holding children to layout and
	 * determine size of a cell
	 */
	clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &childWidth, &childHeight);

	cellWidth=childWidth-((priv->columns-1)*priv->columnSpacing);
	cellWidth=floor(cellWidth/priv->columns);

	cellHeight=childHeight-((priv->rows-1)*priv->rowSpacing);
	cellHeight=floor(cellHeight/priv->rows);

	/* Iterate through children and find largest one
	 * if relative scale was set
	 */
	largestWidth=largestHeight=0.0f;
	if(priv->relativeScale==TRUE)
	{
		gfloat								w, h;

		clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
		while(clutter_actor_iter_next(&iter, &child))
		{
			if(!clutter_actor_is_visible(child)) continue;

			clutter_actor_get_preferred_size(child, NULL, NULL, &w, &h);
			if(w>largestWidth) largestWidth=w;
			if(h>largestHeight) largestHeight=h;
		}
	}

	/* Iterate through child actors and set their new allocation */
	row=col=0;
	x=y=0.0f;
	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
	while(clutter_actor_iter_next(&iter, &child))
	{
		if(!clutter_actor_is_visible(child)) continue;

		/* Get natural size of actor */
		clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight);

		/* If either width or height is 0 then it is visually hidden and we
		 * skip expensive calculation. This also has the nice effect that
		 * do not perform invalid divisions by zero ;)
		 */
		if(childWidth>0.0f && childHeight>0.0f)
		{
			/* Get scale factor needed to apply to width and height.
			 * If no relative scaling should be performed the scale is always 1.0
			 * otherwise it is the scale factor for this actor to the largest one.
			 */
			if(priv->relativeScale==TRUE)
			{
				/* Get scale factors */
				scaleWidth=childWidth/largestWidth;
				scaleHeight=childHeight/largestHeight;
			}
				else scaleWidth=scaleHeight=1.0f;

			/* Get aspect ratio factor */
			aspectRatio=childHeight/childWidth;

			/* Calculate new size of child */
			scaledChildWidth=cellWidth*scaleWidth;
			scaledChildHeight=scaledChildWidth*aspectRatio;
			if(scaledChildHeight>cellHeight)
			{
				scaledChildHeight=cellHeight*scaleHeight;
				scaledChildWidth=scaledChildHeight/aspectRatio;
			}

			/* If upscaling should be prevent check if we are upscaling now */
			if(priv->preventUpscaling)
			{
				if(scaledChildWidth>childWidth)
				{
					scaledChildWidth=childWidth;
					scaledChildHeight=childWidth*aspectRatio;
				}

				if(scaledChildHeight>childHeight)
				{
					scaledChildHeight=childHeight;
					scaledChildWidth=childHeight/aspectRatio;
				}
			}
		}
			else
			{
				/* Visually hidden so do not allocate any space */
				scaledChildWidth=0.0f;
				scaledChildHeight=0.0f;
			}

		/* Set new allocation of child */
		childAllocation.x1=ceil(x+((cellWidth-scaledChildWidth)/2.0f));
		childAllocation.y1=ceil(y+((cellHeight-scaledChildHeight)/2.0f));
		childAllocation.x2=ceil(childAllocation.x1+scaledChildWidth);
		childAllocation.y2=ceil(childAllocation.y1+scaledChildHeight);
		clutter_actor_allocate(child, &childAllocation, inFlags);

		/* Set up for next child */
		col=(col+1) % priv->columns;
		if(col==0) row++;
		x=col*(cellWidth+priv->columnSpacing);
		y=row*(cellHeight+priv->rowSpacing);
	}
}
/* Get largest minimum and natural size of all visible children
 * for calculation of one child and returns the number of visible ones
 */
static gint _xfdashboard_fill_box_layout_get_largest_sizes(XfdashboardFillBoxLayout *self,
															ClutterContainer *inContainer,
															gfloat *outMinWidth,
															gfloat *outNaturalWidth,
															gfloat *outMinHeight,
															gfloat *outNaturalHeight)
{
	XfdashboardFillBoxLayoutPrivate		*priv;
	ClutterActor						*child;
	ClutterActorIter					iter;
	gint								numberChildren;
	gfloat								largestMinWidth, largestNaturalWidth;
	gfloat								largestMinHeight, largestNaturalHeight;
	gfloat								childMinWidth, childNaturalWidth;
	gfloat								childMinHeight, childNaturalHeight;
	ClutterActor						*parent;
	gfloat								parentWidth, parentHeight;
	gfloat								aspectRatio;

	g_return_val_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(self), 0);
	g_return_val_if_fail(CLUTTER_IS_CONTAINER(inContainer), 0);
	g_return_val_if_fail(CLUTTER_IS_ACTOR(inContainer), 0);

	priv=self->priv;

	/* Iterate through all children and determine sizes */
	numberChildren=0;
	largestMinWidth=largestNaturalWidth=largestMinHeight=largestNaturalHeight=0.0f;

	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
	while(clutter_actor_iter_next(&iter, &child))
	{
		/* Only check visible children */
		if(!clutter_actor_is_visible(child)) continue;

		/* Check for largest size */
		clutter_actor_get_preferred_size(child,
											&childMinWidth, &childNaturalWidth,
											&childMinHeight, &childNaturalHeight);

		if(childMinWidth>largestMinWidth) largestMinWidth=childMinWidth;
		if(childNaturalWidth>largestNaturalWidth) largestNaturalWidth=childNaturalWidth;
		if(childMinHeight>largestMinHeight) largestMinHeight=childMinHeight;
		if(childNaturalHeight>largestNaturalHeight) largestNaturalHeight=childNaturalHeight;

		/* Count visible children */
		numberChildren++;
	}

	/* Depending on orientation set sizes to fit into parent actor */
	parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer));
	if(parent)
	{
		aspectRatio=1.0f;

		clutter_actor_get_size(CLUTTER_ACTOR(parent), &parentWidth, &parentHeight);
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
		{
			if(priv->keepAspect==TRUE)
			{
				aspectRatio=largestMinWidth/largestMinHeight;
				largestMinHeight=parentHeight;
				largestMinWidth=largestMinHeight*aspectRatio;

				aspectRatio=largestNaturalWidth/largestNaturalHeight;
				largestNaturalHeight=parentHeight;
				largestNaturalWidth=largestNaturalHeight*aspectRatio;
			}
				else
				{
					largestMinHeight=parentHeight;
					largestNaturalHeight=parentHeight;
				}
		}
			else
			{
				if(priv->keepAspect==TRUE)
				{
					aspectRatio=largestMinHeight/largestMinWidth;
					largestMinWidth=parentWidth;
					largestMinHeight=largestMinWidth*aspectRatio;

					aspectRatio=largestNaturalHeight/largestNaturalWidth;
					largestNaturalWidth=parentWidth;
					largestNaturalHeight=largestNaturalWidth*aspectRatio;
				}
					else
					{
						largestMinWidth=parentWidth;
						largestNaturalWidth=parentWidth;
					}
			}
	}

	/* Set return values */
	if(outMinWidth) *outMinWidth=largestMinWidth;
	if(outNaturalWidth) *outNaturalWidth=largestNaturalWidth;
	if(outMinHeight) *outMinHeight=largestMinHeight;
	if(outNaturalHeight) *outNaturalHeight=largestNaturalHeight;

	/* Return number of visible children */
	return(numberChildren);
}
/* Re-layout and allocate children of container we manage */
static void _xfdashboard_fill_box_layout_allocate(ClutterLayoutManager *inLayoutManager,
													ClutterContainer *inContainer,
													const ClutterActorBox *inAllocation,
													ClutterAllocationFlags inFlags)
{
	XfdashboardFillBoxLayout			*self;
	XfdashboardFillBoxLayoutPrivate		*priv;
	ClutterActor						*child;
	ClutterActorIter					iter;
	gfloat								parentWidth, parentHeight;
	gfloat								homogeneousSize;
	gfloat								x, y, w, h;
	gfloat								aspectRatio;
	ClutterActorBox						childAllocation;

	g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(inLayoutManager));
	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));

	self=XFDASHBOARD_FILL_BOX_LAYOUT(inLayoutManager);
	priv=self->priv;

	/* Get dimension of allocation */
	parentWidth=clutter_actor_box_get_width(inAllocation);
	parentHeight=clutter_actor_box_get_height(inAllocation);

	/* If homogeneous determine sizes for all children */
	if(priv->isHomogeneous==TRUE)
	{
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
		{
			_xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, &homogeneousSize, NULL, NULL);
		}
			else
			{
				_xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, NULL, NULL, &homogeneousSize);
			}
	}

	/* Iterate through children and set their sizes */
	x=y=0.0f;

	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
	while(clutter_actor_iter_next(&iter, &child))
	{
		/* Only set sizes on visible children */
		if(!clutter_actor_is_visible(child)) continue;

		/* Calculate and set new allocation of child */
		if(priv->isHomogeneous==FALSE)
		{
			clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &w, &h);
			if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
			{
				aspectRatio=w/h;
				h=parentHeight;
				w=h*aspectRatio;
			}
				else
				{
					aspectRatio=h/w;
					w=parentWidth;
					h=w*aspectRatio;
				}
		}
			else
			{
				if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
				{
					w=homogeneousSize;
					h=parentHeight;
				}
					else
					{
						w=parentWidth;
						h=homogeneousSize;
					}
			}

		/* Set new allocation of child */
		childAllocation.x1=ceil(x);
		childAllocation.y1=ceil(y);
		childAllocation.x2=ceil(childAllocation.x1+w);
		childAllocation.y2=ceil(childAllocation.y1+h);
		clutter_actor_allocate(child, &childAllocation, inFlags);

		/* Set up for next child */
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) x+=(w+priv->spacing);
			else y+=(h+priv->spacing);
	}
}
/* Get minimum and natural size of all visible children */
static void _xfdashboard_fill_box_layout_get_sizes_for_all(XfdashboardFillBoxLayout *self,
															ClutterContainer *inContainer,
															gfloat *outMinWidth,
															gfloat *outNaturalWidth,
															gfloat *outMinHeight,
															gfloat *outNaturalHeight)
{
	XfdashboardFillBoxLayoutPrivate		*priv;
	ClutterActor						*child;
	ClutterActorIter					iter;
	gint								numberChildren;
	gfloat								minWidth, naturalWidth;
	gfloat								minHeight, naturalHeight;
	gfloat								childMinWidth, childNaturalWidth;
	gfloat								childMinHeight, childNaturalHeight;
	ClutterActor						*parent;
	gfloat								parentWidth, parentHeight;
	gfloat								aspectRatio;

	g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(self));
	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));
	g_return_if_fail(CLUTTER_IS_ACTOR(inContainer));

	priv=self->priv;

	/* Initialize return values */
	numberChildren=0;
	minWidth=naturalWidth=minHeight=naturalHeight=0.0f;

	/* If not homogeneous then iterate through all children and determine sizes ... */
	if(priv->isHomogeneous==FALSE)
	{
		/* Iterate through children and calculate sizes */
		clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
		while(clutter_actor_iter_next(&iter, &child))
		{
			/* Only get sizes of visible children */
			if(!clutter_actor_is_visible(child)) continue;

			/* Count visible children */
			numberChildren++;

			/* Determine sizes of visible child */
			clutter_actor_get_preferred_size(child,
												&childMinWidth, &childNaturalWidth,
												&childMinHeight, &childNaturalHeight);

			if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
			{
				minWidth+=childMinWidth;
				naturalWidth+=childNaturalWidth;
				if(childMinHeight>minHeight) minHeight=childMinHeight;
				if(childNaturalHeight>naturalHeight) naturalHeight=childNaturalHeight;
			}
				else
				{
					minHeight+=childMinHeight;
					naturalHeight+=childNaturalHeight;
					if(childMinWidth>naturalWidth) minWidth=naturalWidth;
					if(childNaturalWidth>naturalHeight) naturalHeight=childNaturalWidth;
				}
		}
	}
		/* ... otherwise get largest minimum and natural size and add spacing */
		else
		{
			/* Get number of visible children and also largest minimum
			 * and natural size
			 */
			numberChildren=_xfdashboard_fill_box_layout_get_largest_sizes(self,
																			inContainer,
																			&childMinWidth, &childNaturalWidth,
																			&childMinHeight, &childNaturalHeight);

			/* Multiply largest sizes with number visible children */
			if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
			{
				minWidth=(numberChildren*childMinWidth);
				naturalWidth=(numberChildren*childNaturalWidth);

				minHeight=childMinHeight;
				naturalHeight=childNaturalHeight;
			}
				else
				{
					minWidth=childMinWidth;
					naturalWidth=childNaturalWidth;

					minHeight=(numberChildren*childMinHeight);
					naturalHeight=(numberChildren*childNaturalHeight);
				}
		}

	/* Add spacing */
	if(numberChildren>0)
	{
		numberChildren--;
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
		{
			minWidth+=numberChildren*priv->spacing;
			naturalWidth+=numberChildren*priv->spacing;
		}
			else
			{
				minHeight+=numberChildren*priv->spacing;
				naturalHeight+=numberChildren*priv->spacing;
			}
	}

	/* Depending on orientation set sizes to fit into parent actor */
	parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer));
	if(parent)
	{
		aspectRatio=1.0f;

		clutter_actor_get_size(CLUTTER_ACTOR(parent), &parentWidth, &parentHeight);
		if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)
		{
			if(priv->keepAspect==TRUE)
			{
				aspectRatio=minWidth/minHeight;
				minHeight=parentHeight;
				minWidth=minHeight*aspectRatio;

				aspectRatio=naturalWidth/naturalHeight;
				naturalHeight=parentHeight;
				naturalWidth=naturalHeight*aspectRatio;
			}
				else
				{
					minHeight=parentHeight;
					naturalHeight=parentHeight;
				}
		}
			else
			{
				if(priv->keepAspect==TRUE)
				{
					aspectRatio=minHeight/minWidth;
					minWidth=parentWidth;
					minHeight=minWidth*aspectRatio;

					aspectRatio=naturalHeight/naturalWidth;
					naturalWidth=parentWidth;
					naturalHeight=naturalWidth*aspectRatio;
				}
					else
					{
						minWidth=parentWidth;
						naturalWidth=parentWidth;
					}
			}
	}

	/* Set return values */
	if(outMinWidth) *outMinWidth=minWidth;
	if(outNaturalWidth) *outNaturalWidth=naturalWidth;
	if(outMinHeight) *outMinHeight=minHeight;
	if(outNaturalHeight) *outNaturalHeight=naturalHeight;
}
Exemplo n.º 7
0
/**
 * clutter_container_child_set:
 * @container: a #ClutterContainer
 * @actor: a #ClutterActor that is a child of @container.
 * @first_prop: name of the first property to be set.
 * @...: value for the first property, followed optionally by more name/value
 * pairs terminated with NULL.
 *
 * Sets container specific properties on the child of a container.
 *
 * Since: 0.8
 */
void
clutter_container_child_set (ClutterContainer *container,
                             ClutterActor     *actor,
                             const gchar      *first_prop,
                             ...)
{
  GObjectClass *klass;
  const gchar *name;
  va_list var_args;
  
  g_return_if_fail (CLUTTER_IS_CONTAINER (container));
  g_return_if_fail (CLUTTER_IS_ACTOR (actor));

  klass = G_OBJECT_GET_CLASS (container);

  va_start (var_args, first_prop);

  name = first_prop;
  while (name)
    {
      GValue value = { 0, };
      gchar *error = NULL;
      GParamSpec *pspec;
    
      pspec = clutter_container_class_find_child_property (klass, name);
      if (!pspec)
        {
          g_warning ("%s: Containers of type '%s' have no child "
                     "property named '%s'",
                     G_STRLOC, G_OBJECT_TYPE_NAME (container), name);
          break;
        }

      if (!(pspec->flags & G_PARAM_WRITABLE))
        {
          g_warning ("%s: Child property '%s' of the container '%s' "
                     "is not writable",
                     G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container));
          break;
        }

#if GLIB_CHECK_VERSION (2, 23, 2)
      G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec),
                            var_args, 0,
                            &error);
#else
      g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
      G_VALUE_COLLECT (&value, var_args, 0, &error);
#endif /* GLIB_CHECK_VERSION (2, 23, 2) */

      if (error)
        {
          /* we intentionally leak the GValue because it might
           * be in an undefined state and calling g_value_unset()
           * on it might crash
           */
          g_warning ("%s: %s", G_STRLOC, error);
          g_free (error);
          break;
        }

      container_set_child_property (container, actor, &value, pspec);

      g_value_unset (&value);

      name = va_arg (var_args, gchar*);
    }

  va_end (var_args);
}
Exemplo n.º 8
0
/**
 * clutter_layout_manager_child_get:
 * @manager: a #ClutterLayoutManager
 * @container: a #ClutterContainer using @manager
 * @actor: a #ClutterActor child of @container
 * @first_property: the name of the first property
 * @Varargs: a list of property name and return location for the value pairs
 *
 * Retrieves the values for a list of properties out of the
 * #ClutterLayoutMeta created by @manager and attached to the
 * child of a @container
 *
 * Since: 1.2
 */
void
clutter_layout_manager_child_get (ClutterLayoutManager *manager,
                                  ClutterContainer     *container,
                                  ClutterActor         *actor,
                                  const gchar          *first_property,
                                  ...)
{
  ClutterLayoutMeta *meta;
  GObjectClass *klass;
  const gchar *pname;
  va_list var_args;

  g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
  g_return_if_fail (CLUTTER_IS_CONTAINER (container));
  g_return_if_fail (CLUTTER_IS_ACTOR (actor));
  g_return_if_fail (first_property != NULL);

  meta = get_child_meta (manager, container, actor);
  if (meta == NULL)
    {
      g_warning ("Layout managers of type '%s' do not support "
                 "layout metadata",
                 g_type_name (G_OBJECT_TYPE (manager)));
      return;
    }

  klass = G_OBJECT_GET_CLASS (meta);

  va_start (var_args, first_property);

  pname = first_property;
  while (pname)
    {
      GValue value = { 0, };
      GParamSpec *pspec;
      gchar *error;
      gboolean res;

      pspec = g_object_class_find_property (klass, pname);
      if (pspec == NULL)
        {
          g_warning ("%s: Layout managers of type '%s' have no layout "
                     "property named '%s'",
                     G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname);
          break;
        }

      g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));

      res = layout_get_property_internal (manager, G_OBJECT (meta),
                                          pspec,
                                          &value);
      if (!res)
        {
          g_value_unset (&value);
          break;
        }

      G_VALUE_LCOPY (&value, var_args, 0, &error);
      if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error);
          g_free (error);
          g_value_unset (&value);
          break;
        }

      g_value_unset (&value);

      pname = va_arg (var_args, gchar*);
    }

  va_end (var_args);
}