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); } }