/* Set/get properties */ static void _xfdashboard_scaled_table_layout_set_property(GObject *inObject, guint inPropID, const GValue *inValue, GParamSpec *inSpec) { XfdashboardScaledTableLayout *self=XFDASHBOARD_SCALED_TABLE_LAYOUT(inObject); switch(inPropID) { case PROP_ROW_SPACING: xfdashboard_scaled_table_layout_set_row_spacing(self, g_value_get_float(inValue)); break; case PROP_COLUMN_SPACING: xfdashboard_scaled_table_layout_set_column_spacing(self, g_value_get_float(inValue)); break; case PROP_RELATIVE_SCALE: xfdashboard_scaled_table_layout_set_relative_scale(self, g_value_get_boolean(inValue)); break; case PROP_PREVENT_UPSCALING: xfdashboard_scaled_table_layout_set_prevent_upscaling(self, g_value_get_boolean(inValue)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec); break; } }
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 and if it is not reentrant */ parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer)); if(parent && !priv->reentrantDetermineHeight) { /* Prevent getting size of parent (reentrance) */ priv->reentrantDetermineHeight=TRUE; /* Get size of parent */ clutter_actor_get_size(CLUTTER_ACTOR(parent), NULL, &maxNaturalHeight); /* Allow getting size of parent again */ priv->reentrantDetermineHeight=FALSE; } /* 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; }
/* Get preferred width/height */ static void _xfdashboard_scaled_table_layout_get_preferred_width(ClutterLayoutManager *self, ClutterContainer *inContainer, gfloat inForHeight, gfloat *outMinWidth, gfloat *outNaturalWidth) { XfdashboardScaledTableLayoutPrivate *priv; gfloat maxMinWidth, maxNaturalWidth; 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 */ maxMinWidth=0.0f; maxNaturalWidth=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), &maxNaturalWidth, NULL); /* Calculate width */ if(priv->columns>0) { maxMinWidth=(priv->columns-1)*priv->columnSpacing; if(maxNaturalWidth==0.0f) maxNaturalWidth=(priv->columns-1)*priv->columnSpacing; } /* Set return values */ if(outMinWidth) *outMinWidth=maxMinWidth; if(outNaturalWidth) *outNaturalWidth=maxNaturalWidth; }
static void _xfdashboard_scaled_table_layout_get_property(GObject *inObject, guint inPropID, GValue *outValue, GParamSpec *inSpec) { XfdashboardScaledTableLayout *self=XFDASHBOARD_SCALED_TABLE_LAYOUT(inObject); switch(inPropID) { case PROP_ROW_SPACING: g_value_set_float(outValue, self->priv->rowSpacing); break; case PROP_COLUMN_SPACING: g_value_set_float(outValue, self->priv->columnSpacing); break; case PROP_RELATIVE_SCALE: g_value_set_boolean(outValue, self->priv->relativeScale); break; case PROP_PREVENT_UPSCALING: g_value_set_boolean(outValue, self->priv->preventUpscaling); break; case PROP_NUMBER_CHILDREN: g_value_set_int(outValue, self->priv->numberChildren); break; case PROP_ROWS: g_value_set_int(outValue, self->priv->rows); break; case PROP_COLUMNS: g_value_set_int(outValue, self->priv->columns); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec); break; } }
/* 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); } }