[Xfce4-commits] [apps/xfdashboard] 01/13: Add new layout manager XfdashboardDynamicTableLayout to fix issue #28

noreply at xfce.org noreply at xfce.org
Tue Mar 24 10:24:59 CET 2015


This is an automated email from the git hooks/post-receive script.

nomad pushed a commit to annotated tag 0.2.1
in repository apps/xfdashboard.

commit ae2dc7adbe281cde67f10249cc8917786f14d69e
Author: Stephan Haller <nomad at froevel.de>
Date:   Tue Jun 24 10:32:21 2014 +0200

    Add new layout manager XfdashboardDynamicTableLayout to fix issue #28
    
    XfdashboardDynamicTableLayout is a layout manager which layouts children in a dynamic table grid. Rows and columns are inserted and deleted automatically depending on the number of visible child actors. Usually it will prefer more columns over rows.
---
 src/Makefile.am            |    2 +
 src/applications-view.c    |    7 +-
 src/dynamic-table-layout.c |  695 ++++++++++++++++++++++++++++++++++++++++++++
 src/dynamic-table-layout.h |   80 +++++
 4 files changed, 780 insertions(+), 4 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 6a4ed09..c678b68 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,7 @@ xfdashboard_headers = \
 	collapse-box.h \
 	drag-action.h \
 	drop-action.h \
+	dynamic-table-layout.h \
 	fill-box-layout.h \
 	focusable.h \
 	focus-manager.h \
@@ -79,6 +80,7 @@ xfdashboard_SOURCES = \
 	button.c \
 	click-action.c \
 	collapse-box.c \
+	dynamic-table-layout.c \
 	drag-action.c \
 	drop-action.c \
 	fill-box-layout.c \
diff --git a/src/applications-view.c b/src/applications-view.c
index aa70eb1..549ccf4 100644
--- a/src/applications-view.c
+++ b/src/applications-view.c
@@ -40,6 +40,7 @@
 #include "stylable.h"
 #include "focusable.h"
 #include "focus-manager.h"
+#include "dynamic-table-layout.h"
 
 /* Define this class in GObject system */
 static void _xfdashboard_applications_view_focusable_iface_init(XfdashboardFocusableInterface *iface);
@@ -993,10 +994,8 @@ void xfdashboard_applications_view_set_view_mode(XfdashboardApplicationsView *se
 				break;
 
 			case XFDASHBOARD_VIEW_MODE_ICON:
-				priv->layout=clutter_flow_layout_new(CLUTTER_FLOW_HORIZONTAL);
-				clutter_flow_layout_set_column_spacing(CLUTTER_FLOW_LAYOUT(priv->layout), priv->spacing);
-				clutter_flow_layout_set_row_spacing(CLUTTER_FLOW_LAYOUT(priv->layout), priv->spacing);
-				clutter_flow_layout_set_homogeneous(CLUTTER_FLOW_LAYOUT(priv->layout), TRUE);
+				priv->layout=xfdashboard_dynamic_table_layout_new();
+				xfdashboard_dynamic_table_layout_set_spacing(XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(priv->layout), priv->spacing);
 				clutter_actor_set_layout_manager(CLUTTER_ACTOR(self), priv->layout);
 				break;
 
diff --git a/src/dynamic-table-layout.c b/src/dynamic-table-layout.c
new file mode 100644
index 0000000..a4b32bc
--- /dev/null
+++ b/src/dynamic-table-layout.c
@@ -0,0 +1,695 @@
+/*
+ * dynamic-table-layout: Layouts children in a dynamic table grid
+ *                       (rows and columns are inserted and deleted
+ *                       automatically depending on the number of
+ *                       child actors).
+ * 
+ * Copyright 2012-2014 Stephan Haller <nomad at froevel.de>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ * 
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dynamic-table-layout.h"
+
+#include <glib/gi18n-lib.h>
+#include <clutter/clutter.h>
+#include <math.h>
+
+/* Define this class in GObject system */
+G_DEFINE_TYPE(XfdashboardDynamicTableLayout,
+				xfdashboard_dynamic_table_layout,
+				CLUTTER_TYPE_LAYOUT_MANAGER)
+
+/* Private structure - access only by public API if needed */
+#define XFDASHBOARD_DYNAMIC_TABLE_LAYOUT_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT, XfdashboardDynamicTableLayoutPrivate))
+
+struct _XfdashboardDynamicTableLayoutPrivate
+{
+	/* Properties related */
+	gfloat		rowSpacing;
+	gfloat		columnSpacing;
+
+	/* Instance related */
+	gint		rows;
+	gint		columns;
+	gint		numberChildren;
+
+	GArray		*columnCoords;
+	GArray		*rowCoords;
+};
+
+/* Properties */
+enum
+{
+	PROP_0,
+
+	PROP_ROW_SPACING,
+	PROP_COLUMN_SPACING,
+
+	PROP_NUMBER_CHILDREN,
+	PROP_ROWS,
+	PROP_COLUMNS,
+
+	PROP_LAST
+};
+
+static GParamSpec* XfdashboardDynamicTableLayoutProperties[PROP_LAST]={ 0, };
+
+/* IMPLEMENTATION: Private variables and methods */
+
+/* Updates data needed for layout */
+static void _xfdashboard_dynamic_table_layout_update_layout_data(XfdashboardDynamicTableLayout *self,
+																	ClutterContainer *inContainer,
+																	gfloat inWidth,
+																	gfloat inHeight)
+{
+	XfdashboardDynamicTableLayoutPrivate		*priv;
+	ClutterActorIter							iter;
+	ClutterActor								*child;
+	gint										numberChildren;
+	gint										rows, columns;
+	gfloat										childWidth, childHeight;
+	gfloat										largestWidth, largestHeight;
+	gint										i;
+	gfloat										x, y;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_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));
+g_message("%s[begin]: size=%.2f x %.2f", __func__, inWidth, inHeight);
+
+	/* Step one: Get number of visible child actors and determine largest width
+	 * and height of all visible child actors' natural size.
+	 */
+	numberChildren=0;
+	largestWidth=largestHeight=0.0f;
+	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
+	while(clutter_actor_iter_next(&iter, &child))
+	{
+		/* Handle only visible actors */
+		if(CLUTTER_ACTOR_IS_VISIBLE(child))
+		{
+			/* Count visible children */
+			numberChildren++;
+
+			/* Check if either width and/or height of child is the largest one */
+			clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight);
+			largestWidth=MAX(largestWidth, childWidth);
+			largestHeight=MAX(largestHeight, childHeight);
+		}
+	}
+g_message("%s: number-children=%d, largest=%.2f x %.2f", __func__, numberChildren, largestWidth, largestHeight);
+
+	if(numberChildren!=priv->numberChildren)
+	{
+		priv->numberChildren=numberChildren;
+		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardDynamicTableLayoutProperties[PROP_NUMBER_CHILDREN]);
+	}
+
+	/* Step two: Determine number of rows and columns */
+	rows=columns=0;
+	if(inWidth<0.0f && inHeight<0.0f)
+	{
+		columns=priv->numberChildren;
+		rows=1;
+	}
+		else if(inWidth>0.0f)
+		{
+			columns=MIN(ceil(inWidth/largestWidth), priv->numberChildren);
+			do
+			{
+				childWidth=(columns*largestWidth)+((columns-1)*priv->columnSpacing);
+				columns--;
+			}
+			while(columns>1 && childWidth>inWidth);
+
+			largestWidth=floor(inWidth-((columns-1)*priv->columnSpacing))/columns;
+			rows=ceil((double)priv->numberChildren / (double)columns);
+		}
+		else if(inHeight>0.0f)
+		{
+			// TODO: Take row spacing into account
+			rows=floor(inHeight/largestHeight);
+			rows=MIN(rows, priv->numberChildren);
+			columns=ceil((double)priv->numberChildren / (double)rows);
+		}
+g_message("%s: columns=%d, rows=%d", __func__, columns, rows);
+
+	if(rows!=priv->rows)
+	{
+		priv->rows=rows;
+		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardDynamicTableLayoutProperties[PROP_ROWS]);
+	}
+
+	if(columns!=priv->columns)
+	{
+		priv->columns=columns;
+		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardDynamicTableLayoutProperties[PROP_COLUMNS]);
+	}
+
+	/* Step three: Determine column and row coordinates */
+	if(priv->columnCoords)
+	{
+		g_array_free(priv->columnCoords, TRUE);
+		priv->columnCoords=NULL;
+	}
+
+	priv->columnCoords=g_array_new(FALSE, FALSE, sizeof(gfloat));
+	x=0.0f;
+	i=0;
+	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
+	while(clutter_actor_iter_next(&iter, &child))
+	{
+		/* Handle only visible actors */
+		if(CLUTTER_ACTOR_IS_VISIBLE(child))
+		{
+			g_array_append_val(priv->columnCoords, x);
+g_message("%s: Column %d=%.2f", __func__, i, x);
+			x+=(largestWidth+priv->columnSpacing);
+
+			/* Increase counter for visible children */
+			i++;
+		}
+	}
+
+	g_array_append_val(priv->columnCoords, x);
+
+	/* Step four: Determine row coordinates */
+	if(priv->rowCoords)
+	{
+		g_array_free(priv->rowCoords, TRUE);
+		priv->rowCoords=NULL;
+	}
+
+	priv->rowCoords=g_array_new(FALSE, FALSE, sizeof(gfloat));
+	largestHeight=0.0f;
+	y=-priv->rowSpacing;
+	i=0;
+	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
+	while(clutter_actor_iter_next(&iter, &child))
+	{
+		/* Handle only visible actors */
+		if(CLUTTER_ACTOR_IS_VISIBLE(child))
+		{
+			/* If it is the first columns in row, calculate y-coordinate
+			 * and append it to array.
+			 */
+			if((i % priv->columns)==0)
+			{
+				y+=largestHeight+priv->rowSpacing;
+				g_array_append_val(priv->rowCoords, y);
+g_message("%s: Row %d=%.2f", __func__, (i/priv->columns), y);
+				largestHeight=0.0f;
+			}
+
+			/* Determine largest height in row */
+			clutter_actor_get_preferred_size(child, NULL, NULL, NULL, &childHeight);
+			largestHeight=MAX(largestHeight, childHeight);
+
+			/* Increase counter for visible children */
+			i++;
+		}
+	}
+
+	y+=largestHeight;
+	g_array_append_val(priv->rowCoords, y);
+g_message("%s: Row[last] %d=%.2f", __func__, (i/priv->columns), y);
+
+	/* Thaw notification */
+	g_object_thaw_notify(G_OBJECT(self));
+g_message("%s[end]", __func__);
+}
+
+/* IMPLEMENTATION: ClutterLayoutManager */
+
+/* Get preferred width/height */
+static void _xfdashboard_dynamic_table_layout_get_preferred_width(ClutterLayoutManager *self,
+																	ClutterContainer *inContainer,
+																	gfloat inForHeight,
+																	gfloat *outMinWidth,
+																	gfloat *outNaturalWidth)
+{
+	XfdashboardDynamicTableLayoutPrivate	*priv;
+	gfloat									maxMinWidth, maxNaturalWidth;
+	ClutterActor							*parent;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self));
+	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));
+
+	priv=XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(self)->priv;
+
+g_message("%s[begin]: for-height=%.2f, column-spacing=%.2f", __func__, inForHeight, priv->columnSpacing);
+
+	/* Set up default values */
+	maxMinWidth=0.0f;
+	maxNaturalWidth=0.0f;
+
+	/* Update data needed for layout */
+	_xfdashboard_dynamic_table_layout_update_layout_data(XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(self), inContainer, -1.0f, inForHeight);
+
+	/* 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=g_array_index(priv->columnCoords, gfloat, priv->columns);
+	}
+
+	/* Set return values */
+	if(outMinWidth) *outMinWidth=maxMinWidth;
+	if(outNaturalWidth) *outNaturalWidth=maxNaturalWidth;
+g_message("%s[end]: min-width=%.2f, natural-width=%.2f", __func__, maxMinWidth, maxNaturalWidth);
+}
+
+static void _xfdashboard_dynamic_table_layout_get_preferred_height(ClutterLayoutManager *self,
+																	ClutterContainer *inContainer,
+																	gfloat inForWidth,
+																	gfloat *outMinHeight,
+																	gfloat *outNaturalHeight)
+{
+	XfdashboardDynamicTableLayoutPrivate	*priv;
+	gfloat									maxMinHeight, maxNaturalHeight;
+	ClutterActor							*parent;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self));
+	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));
+
+	priv=XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(self)->priv;
+
+g_message("%s[begin]: for-width=%.2f, row-spacing=%.2f", __func__, inForWidth, priv->rowSpacing);
+
+	/* Set up default values */
+	maxMinHeight=0.0f;
+	maxNaturalHeight=0.0f;
+
+	/* Update data needed for layout */
+	_xfdashboard_dynamic_table_layout_update_layout_data(XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(self), inContainer, inForWidth, -1.0f);
+
+	/* 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=g_array_index(priv->rowCoords, gfloat, priv->rows);
+	}
+
+	/* Set return values */
+	if(outMinHeight) *outMinHeight=maxMinHeight;
+	if(outNaturalHeight) *outNaturalHeight=maxNaturalHeight;
+g_message("%s[end]: min-height=%.2f, natural-height=%.2f", __func__, maxMinHeight, maxNaturalHeight);
+}
+
+/* Re-layout and allocate children of container we manage */
+static void _xfdashboard_dynamic_table_layout_allocate(ClutterLayoutManager *self,
+														ClutterContainer *inContainer,
+														const ClutterActorBox *inAllocation,
+														ClutterAllocationFlags inFlags)
+{
+	XfdashboardDynamicTableLayoutPrivate	*priv;
+	gfloat									width, height;
+	ClutterActorIter						iter;
+	ClutterActor							*child;
+	gint									column, row, i;
+	gfloat									left, right, top, bottom;
+	gfloat									childWidth, childHeight;
+	ClutterActorBox							childAllocation;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self));
+	g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer));
+	g_return_if_fail(CLUTTER_IS_ACTOR(inContainer));
+
+	priv=XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(self)->priv;
+
+	/* Get size of container holding children to layout */
+	width=clutter_actor_box_get_width(inAllocation);
+	height=clutter_actor_box_get_height(inAllocation);
+g_message("%s[begin]: allocation=%.2f x %.2f", __func__, width, height);
+
+	/* Update data needed for layout */
+	_xfdashboard_dynamic_table_layout_update_layout_data(XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(self),
+															inContainer,
+															width,
+															height);
+
+	/* Determine allocation for each visible child */
+	i=0;
+	clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer));
+	while(clutter_actor_iter_next(&iter, &child))
+	{
+		/* Handle only visible actors */
+		if(CLUTTER_ACTOR_IS_VISIBLE(child))
+		{
+			/* Get column and row for child */
+			column=floor(i % priv->columns);
+			row=floor(i / priv->columns);
+
+			/* Get outer allocation for child */
+			left=g_array_index(priv->columnCoords, gfloat, column);
+			right=g_array_index(priv->columnCoords, gfloat, column+1)-priv->columnSpacing;
+			top=g_array_index(priv->rowCoords, gfloat, row);
+			bottom=g_array_index(priv->rowCoords, gfloat, row+1)-priv->rowSpacing;
+g_message("%s: column=%d, row=%d -> %.2f , %.2f [%.2f x %.2f]", __func__, column, row, left, top, right-left, bottom-top);
+
+			/* Get inner allocation for child */
+			clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight);
+
+			left+=(right-left-childWidth)/2.0f;
+			right=left+childWidth;
+
+			top+=(bottom-top-childHeight)/2.0f;
+			bottom=top+childHeight;
+
+			/* Set new allocation of child */
+			childAllocation.x1=floor(left);
+			childAllocation.y1=floor(top);
+			childAllocation.x2=floor(right);
+			childAllocation.y2=floor(bottom);
+			clutter_actor_allocate(child, &childAllocation, inFlags);
+
+			/* Increase counter for visible children */
+			i++;
+		}
+	}
+
+g_message("%s[end]", __func__);
+}
+
+/* IMPLEMENTATION: GObject */
+
+/* Dispose this object */
+static void _xfdashboard_dynamic_table_layout_dispose(GObject *inObject)
+{
+	XfdashboardDynamicTableLayout			*self=XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(inObject);
+	XfdashboardDynamicTableLayoutPrivate	*priv=self->priv;
+
+	/* Dispose allocated resources */
+	if(priv->columnCoords)
+	{
+		g_array_free(priv->columnCoords, TRUE);
+		priv->columnCoords=NULL;
+	}
+
+	if(priv->rowCoords)
+	{
+		g_array_free(priv->rowCoords, TRUE);
+		priv->rowCoords=NULL;
+	}
+
+	/* Call parent's class dispose method */
+	G_OBJECT_CLASS(xfdashboard_dynamic_table_layout_parent_class)->dispose(inObject);
+}
+
+/* Set/get properties */
+static void _xfdashboard_dynamic_table_layout_set_property(GObject *inObject,
+															guint inPropID,
+															const GValue *inValue,
+															GParamSpec *inSpec)
+{
+	XfdashboardDynamicTableLayout	*self=XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(inObject);
+	
+	switch(inPropID)
+	{
+		case PROP_ROW_SPACING:
+			xfdashboard_dynamic_table_layout_set_row_spacing(self, g_value_get_float(inValue));
+			break;
+
+		case PROP_COLUMN_SPACING:
+			xfdashboard_dynamic_table_layout_set_column_spacing(self, g_value_get_float(inValue));
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
+			break;
+	}
+}
+
+static void _xfdashboard_dynamic_table_layout_get_property(GObject *inObject,
+															guint inPropID,
+															GValue *outValue,
+															GParamSpec *inSpec)
+{
+	XfdashboardDynamicTableLayout	*self=XFDASHBOARD_DYNAMIC_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_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;
+	}
+}
+
+/* Class initialization
+ * Override functions in parent classes and define properties
+ * and signals
+ */
+static void xfdashboard_dynamic_table_layout_class_init(XfdashboardDynamicTableLayoutClass *klass)
+{
+	ClutterLayoutManagerClass	*layoutClass=CLUTTER_LAYOUT_MANAGER_CLASS(klass);
+	GObjectClass				*gobjectClass=G_OBJECT_CLASS(klass);
+
+	/* Override functions */
+	layoutClass->get_preferred_width=_xfdashboard_dynamic_table_layout_get_preferred_width;
+	layoutClass->get_preferred_height=_xfdashboard_dynamic_table_layout_get_preferred_height;
+	layoutClass->allocate=_xfdashboard_dynamic_table_layout_allocate;
+
+	gobjectClass->dispose=_xfdashboard_dynamic_table_layout_dispose;
+	gobjectClass->set_property=_xfdashboard_dynamic_table_layout_set_property;
+	gobjectClass->get_property=_xfdashboard_dynamic_table_layout_get_property;
+
+	/* Set up private structure */
+	g_type_class_add_private(klass, sizeof(XfdashboardDynamicTableLayoutPrivate));
+
+	/* Define properties */
+	XfdashboardDynamicTableLayoutProperties[PROP_ROW_SPACING]=
+		g_param_spec_float("row-spacing",
+								_("Row spacing"),
+								_("The spacing between rows in table"),
+								0.0f,
+								G_MAXFLOAT,
+								0.0f,
+								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	XfdashboardDynamicTableLayoutProperties[PROP_COLUMN_SPACING]=
+		g_param_spec_float("column-spacing",
+								_("Column spacing"),
+								_("The spacing between columns in table"),
+								0.0f,
+								G_MAXFLOAT,
+								0.0f,
+								G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	XfdashboardDynamicTableLayoutProperties[PROP_NUMBER_CHILDREN]=
+		g_param_spec_float("number-children",
+								_("Number children"),
+								_("Current number of child actors in this layout"),
+								0,
+								G_MAXINT,
+								0,
+								G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	XfdashboardDynamicTableLayoutProperties[PROP_ROWS]=
+		g_param_spec_float("rows",
+								_("Rows"),
+								_("Current number of rows in this layout"),
+								0,
+								G_MAXINT,
+								0,
+								G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	XfdashboardDynamicTableLayoutProperties[PROP_COLUMNS]=
+		g_param_spec_float("columns",
+								_("Columns"),
+								_("Current number of columns in this layout"),
+								0,
+								G_MAXINT,
+								0,
+								G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+	
+	g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardDynamicTableLayoutProperties);
+}
+
+/* Object initialization
+ * Create private structure and set up default values
+ */
+static void xfdashboard_dynamic_table_layout_init(XfdashboardDynamicTableLayout *self)
+{
+	XfdashboardDynamicTableLayoutPrivate	*priv;
+
+	priv=self->priv=XFDASHBOARD_DYNAMIC_TABLE_LAYOUT_GET_PRIVATE(self);
+
+	/* Set default values */
+	priv->rowSpacing=0.0f;
+	priv->columnSpacing=0.0f;
+
+	priv->rows=0;
+	priv->columns=0;
+	priv->numberChildren=0;
+	priv->columnCoords=NULL;
+	priv->rowCoords=NULL;
+}
+
+/* IMPLEMENTATION: Public API */
+
+/* Create new instance */
+ClutterLayoutManager* xfdashboard_dynamic_table_layout_new(void)
+{
+	return(CLUTTER_LAYOUT_MANAGER(g_object_new(XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT, NULL)));
+}
+
+/* Get number of (visible) children which will be layouted */
+gint xfdashboard_dynamic_table_layout_get_number_children(XfdashboardDynamicTableLayout *self)
+{
+	g_return_val_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self), 0);
+
+	return(self->priv->numberChildren);
+}
+
+/* Get number of rows */
+gint xfdashboard_dynamic_table_layout_get_rows(XfdashboardDynamicTableLayout *self)
+{
+	g_return_val_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self), 0);
+
+	return(self->priv->rows);
+}
+
+/* Get number of columns */
+gint xfdashboard_dynamic_table_layout_get_columns(XfdashboardDynamicTableLayout *self)
+{
+	g_return_val_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self), 0);
+
+	return(self->priv->columns);
+}
+
+/* Set relative row and column spacing to same value at once */
+void xfdashboard_dynamic_table_layout_set_spacing(XfdashboardDynamicTableLayout *self, gfloat inSpacing)
+{
+	XfdashboardDynamicTableLayoutPrivate		*priv;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self));
+	g_return_if_fail(inSpacing>=0.0f);
+
+	priv=self->priv;
+
+	/* Set new values if changed */
+	if(priv->rowSpacing!=inSpacing || priv->columnSpacing!=inSpacing)
+	{
+		/* Set new values and notify about properties changes */
+		priv->rowSpacing=inSpacing;
+		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardDynamicTableLayoutProperties[PROP_ROW_SPACING]);
+
+		priv->columnSpacing=inSpacing;
+		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardDynamicTableLayoutProperties[PROP_COLUMN_SPACING]);
+
+		/* Notify for upcoming layout changes */
+		clutter_layout_manager_layout_changed(CLUTTER_LAYOUT_MANAGER(self));
+	}
+}
+
+/* Get/set row spacing */
+gfloat xfdashboard_dynamic_table_layout_get_row_spacing(XfdashboardDynamicTableLayout *self)
+{
+	g_return_val_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self), 0.0f);
+
+	return(self->priv->rowSpacing);
+}
+
+void xfdashboard_dynamic_table_layout_set_row_spacing(XfdashboardDynamicTableLayout *self, gfloat inSpacing)
+{
+	XfdashboardDynamicTableLayoutPrivate		*priv;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self));
+	g_return_if_fail(inSpacing>=0.0f);
+
+	priv=self->priv;
+
+	/* Set new value if changed */
+	if(priv->rowSpacing!=inSpacing)
+	{
+		/* Set new value and notify about property change */
+		priv->rowSpacing=inSpacing;
+		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardDynamicTableLayoutProperties[PROP_ROW_SPACING]);
+
+		/* Notify for upcoming layout changes */
+		clutter_layout_manager_layout_changed(CLUTTER_LAYOUT_MANAGER(self));
+	}
+}
+
+/* Get/set columns spacing */
+gfloat xfdashboard_dynamic_table_layout_get_column_spacing(XfdashboardDynamicTableLayout *self)
+{
+	g_return_val_if_fail(XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(self), 0.0f);
+
+	return(self->priv->columnSpacing);
+}
+
+void xfdashboard_dynamic_table_layout_set_column_spacing(XfdashboardDynamicTableLayout *self, gfloat inSpacing)
+{
+	XfdashboardDynamicTableLayoutPrivate		*priv;
+
+	g_return_if_fail(XFDASHBOARD_IS_DYNAMIC_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), XfdashboardDynamicTableLayoutProperties[PROP_COLUMN_SPACING]);
+
+		/* Notify for upcoming layout changes */
+		clutter_layout_manager_layout_changed(CLUTTER_LAYOUT_MANAGER(self));
+	}
+}
diff --git a/src/dynamic-table-layout.h b/src/dynamic-table-layout.h
new file mode 100644
index 0000000..de6aa01
--- /dev/null
+++ b/src/dynamic-table-layout.h
@@ -0,0 +1,80 @@
+/*
+ * dynamic-table-layout: Layouts children in a dynamic table grid
+ *                       (rows and columns are inserted and deleted
+ *                       automatically depending on the number of
+ *                       child actors).
+ * 
+ * Copyright 2012-2014 Stephan Haller <nomad at froevel.de>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ * 
+ * 
+ */
+
+#ifndef __XFDASHBOARD_DYNAMIC_TABLE_LAYOUT__
+#define __XFDASHBOARD_DYNAMIC_TABLE_LAYOUT__
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT				(xfdashboard_dynamic_table_layout_get_type())
+#define XFDASHBOARD_DYNAMIC_TABLE_LAYOUT(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT, XfdashboardDynamicTableLayout))
+#define XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT))
+#define XFDASHBOARD_DYNAMIC_TABLE_LAYOUT_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT, XfdashboardDynamicTableLayoutClass))
+#define XFDASHBOARD_IS_DYNAMIC_TABLE_LAYOUT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT))
+#define XFDASHBOARD_DYNAMIC_TABLE_LAYOUT_GET_CLASS(obj)		(G_TYPE_INSTANCE_GET_CLASS((obj), XFDASHBOARD_TYPE_DYNAMIC_TABLE_LAYOUT, XfdashboardDynamicTableLayoutClass))
+
+typedef struct _XfdashboardDynamicTableLayout				XfdashboardDynamicTableLayout;
+typedef struct _XfdashboardDynamicTableLayoutPrivate		XfdashboardDynamicTableLayoutPrivate;
+typedef struct _XfdashboardDynamicTableLayoutClass			XfdashboardDynamicTableLayoutClass;
+
+struct _XfdashboardDynamicTableLayout
+{
+	/* Parent instance */
+	ClutterLayoutManager 					parent_instance;
+
+	/* Private structure */
+	XfdashboardDynamicTableLayoutPrivate	*priv;
+};
+
+struct _XfdashboardDynamicTableLayoutClass
+{
+	/*< private >*/
+	/* Parent class */
+	ClutterLayoutManagerClass				parent_class;
+};
+
+/* Public API */
+GType xfdashboard_dynamic_table_layout_get_type(void) G_GNUC_CONST;
+
+ClutterLayoutManager* xfdashboard_dynamic_table_layout_new(void);
+
+gint xfdashboard_dynamic_table_layout_get_number_children(XfdashboardDynamicTableLayout *self);
+gint xfdashboard_dynamic_table_layout_get_rows(XfdashboardDynamicTableLayout *self);
+gint xfdashboard_dynamic_table_layout_get_columns(XfdashboardDynamicTableLayout *self);
+
+void xfdashboard_dynamic_table_layout_set_spacing(XfdashboardDynamicTableLayout *self, gfloat inSpacing);
+
+gfloat xfdashboard_dynamic_table_layout_get_row_spacing(XfdashboardDynamicTableLayout *self);
+void xfdashboard_dynamic_table_layout_set_row_spacing(XfdashboardDynamicTableLayout *self, gfloat inSpacing);
+
+gfloat xfdashboard_dynamic_table_layout_get_column_spacing(XfdashboardDynamicTableLayout *self);
+void xfdashboard_dynamic_table_layout_set_column_spacing(XfdashboardDynamicTableLayout *self, gfloat inSpacing);
+
+G_END_DECLS
+
+#endif	/* __XFDASHBOARD_DYNAMIC_TABLE_LAYOUT__ */

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list