void xfdashboard_scaled_table_layout_set_column_spacing(XfdashboardScaledTableLayout *self, gfloat inSpacing)
{
	XfdashboardScaledTableLayoutPrivate		*priv;

	g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self));
	g_return_if_fail(inSpacing>=0.0f);

	priv=self->priv;

	/* Set new value if changed */
	if(priv->columnSpacing!=inSpacing)
	{
		/* Set new value and notify about property change */
		priv->columnSpacing=inSpacing;
		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_COLUMN_SPACING]);

		/* Notify for upcoming layout changes */
		clutter_layout_manager_layout_changed(CLUTTER_LAYOUT_MANAGER(self));
	}
}
static void _xfdashboard_scaled_table_layout_get_preferred_height(ClutterLayoutManager *self,
        ClutterContainer *inContainer,
        gfloat inForWidth,
        gfloat *outMinHeight,
        gfloat *outNaturalHeight)
{
    XfdashboardScaledTableLayoutPrivate		*priv;
    gfloat									maxMinHeight, maxNaturalHeight;
    ClutterActor							*parent;

    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;

    /* Set up default values */
    maxMinHeight=0.0f;
    maxNaturalHeight=0.0f;

    /* Update number of rows and columns needed for layout */
    _xfdashboard_scaled_table_layout_update_rows_and_columns(XFDASHBOARD_SCALED_TABLE_LAYOUT(self), inContainer);

    /* Get size of parent if this child is parented */
    parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer));
    if(parent) clutter_actor_get_size(CLUTTER_ACTOR(parent), NULL, &maxNaturalHeight);

    /* Calculate height */
    if(priv->rows>0)
    {
        maxMinHeight=(priv->rows-1)*priv->rowSpacing;
        if(maxNaturalHeight==0.0f) maxNaturalHeight=(priv->rows-1)*priv->rowSpacing;
    }

    /* Set return values */
    if(outMinHeight) *outMinHeight=maxMinHeight;
    if(outNaturalHeight) *outNaturalHeight=maxNaturalHeight;
}
/* 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));
}
/* Get/set columns spacing */
gfloat xfdashboard_scaled_table_layout_get_column_spacing(XfdashboardScaledTableLayout *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self), 0.0f);

    return(self->priv->columnSpacing);
}
/* Get/set if layout manager should prevent to size any child larger than its real size */
gboolean xfdashboard_scaled_table_layout_get_prevent_upscaling(XfdashboardScaledTableLayout *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self), FALSE);

    return(self->priv->preventUpscaling);
}
/* Get/set relative scaling of all children to largest one */
gboolean xfdashboard_scaled_table_layout_get_relative_scale(XfdashboardScaledTableLayout *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self), FALSE);

    return(self->priv->relativeScale);
}
/* Get number of columns */
gint xfdashboard_scaled_table_layout_get_columns(XfdashboardScaledTableLayout *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self), 0);

    return(self->priv->columns);
}
/* Get number of (visible) children which will be layouted */
gint xfdashboard_scaled_table_layout_get_number_children(XfdashboardScaledTableLayout *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self), 0);

    return(self->priv->numberChildren);
}
/* 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);
    }
}