summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCosimo Cecchi <cosimoc@gnome.org>2013-09-19 11:16:27 -0700
committerCosimo Cecchi <cosimoc@gnome.org>2013-09-19 11:16:27 -0700
commitd0e2c752911915d0f168fc2e407799d999f35863 (patch)
treee10eed5ecbafee547bbb8c97e6901a4b9612940a
parentbee3cf2a182ac6f6fadd0dd5d24768e5a5837521 (diff)
parent114062bf62e805abf5e0a5ce16f7d77e94b90296 (diff)
Merge pull request #309 from endlessm/issues/1015
Improvements to EosFlexyGrid
-rw-r--r--.gitignore5
-rw-r--r--docs/reference/endless/Makefile.am3
-rw-r--r--docs/reference/endless/endless-docs.xml1
-rw-r--r--docs/reference/endless/endless-sections.txt37
-rw-r--r--endless/eosflexygrid.c774
-rw-r--r--endless/eosflexygrid.h32
-rw-r--r--endless/eosflexygridcell.c64
-rw-r--r--test/Makefile.am6
-rw-r--r--test/flexy-grid.c107
-rw-r--r--test/run-tests.c1
-rw-r--r--test/run-tests.h1
-rw-r--r--test/test-flexy-grid.c75
12 files changed, 827 insertions, 279 deletions
diff --git a/.gitignore b/.gitignore
index 5f1f7aa..0cf83de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Build products
endless-0.pc
test/run-tests
+test/flexy-grid
test/smoke-tests/hello
Endless-0.gir
Endless-0.typelib
@@ -128,3 +129,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
+
+# Editor stuff
+*~
+*.swp
diff --git a/docs/reference/endless/Makefile.am b/docs/reference/endless/Makefile.am
index 420200c..9ad8c86 100644
--- a/docs/reference/endless/Makefile.am
+++ b/docs/reference/endless/Makefile.am
@@ -53,7 +53,8 @@ IGNORE_HFILES= eosinit-private.h \
eostopbar-private.h \
eosmainarea-private.h \
eosactionmenu-private.h \
- eospagemanager-private.h
+ eospagemanager-private.h \
+ eosflexygrid-private.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/docs/reference/endless/endless-docs.xml b/docs/reference/endless/endless-docs.xml
index e11497c..c602ed2 100644
--- a/docs/reference/endless/endless-docs.xml
+++ b/docs/reference/endless/endless-docs.xml
@@ -22,6 +22,7 @@
<xi:include href="xml/page-manager.xml"/>
<xi:include href="xml/splash-page-manager.xml"/>
<xi:include href="xml/action-button.xml"/>
+ <xi:include href="xml/flexy-grid.xml"/>
<!--<xi:include href="xml/hello.xml"/>-->
</chapter>
diff --git a/docs/reference/endless/endless-sections.txt b/docs/reference/endless/endless-sections.txt
index 805bcf4..a9c70f0 100644
--- a/docs/reference/endless/endless-sections.txt
+++ b/docs/reference/endless/endless-sections.txt
@@ -135,4 +135,39 @@ EosActionButtonClass
eos_action_button_get_type
<SUBSECTION Private>
EosActionButtonPrivate
-</SECTION> \ No newline at end of file
+</SECTION>
+
+<SECTION>
+<FILE>flexy-grid</FILE>
+EosFlexyGrid
+EosFlexyGridCell
+eos_flexy_grid_new
+eos_flexy_grid_set_cell_size
+eos_flexy_grid_get_cell_size
+eos_flexy_grid_set_cell_spacing
+eos_flexy_grid_get_cell_spacing
+eos_flexy_grid_insert
+EosFlexyGridSortFunc
+eos_flexy_grid_set_sort_func
+eos_flexy_grid_get_cell_at_coords
+<SUBSECTION>
+eos_flexy_grid_cell_new
+eos_flexy_grid_cell_set_shape
+eos_flexy_grid_cell_get_shape
+<SUBSECTION Standard>
+EOS_TYPE_FLEXY_GRID
+EOS_FLEXY_GRID
+EOS_FLEXY_GRID_CLASS
+EOS_FLEXY_GRID_GET_CLAS
+EOS_IS_FLEXY_GRID
+EOS_IS_FLEXY_GRID_CLASS
+EOS_TYPE_FLEXY_GRID_CELL
+EOS_FLEXY_GRID_CELL
+EOS_FLEXY_GRID_CELL_CLASS
+EOS_FLEXY_GRID_CELL_GET_CLASS
+EOS_IS_FLEXY_GRID_CELL
+EOS_IS_FLEXY_GRID_CELL_CLASS
+<SUBSECTION Private>
+eos_flexy_grid_get_type
+eos_flexy_grid_cell_get_type
+</SECTION>
diff --git a/endless/eosflexygrid.c b/endless/eosflexygrid.c
index 6663a73..b695cc1 100644
--- a/endless/eosflexygrid.c
+++ b/endless/eosflexygrid.c
@@ -1,9 +1,20 @@
/* Copyright 2013 Endless Mobile, Inc. */
+/**
+ * SECTION:flexy-grid
+ * @Title: EosFlexyGrid
+ * @Short_Description: A flexible grid layout manager
+ *
+ * The #EosFlexyGrid widget provides a grid of cells in a layout controlled
+ * by the shape of the cells themselves, through the #EosFlexyGridCell:shape
+ * property of #EosFlexyGridCell.
+ */
+
#include "config.h"
#include "eosflexygrid-private.h"
+#include <string.h>
#include <glib-object.h>
#include <gtk/gtk.h>
@@ -14,14 +25,8 @@
#ifdef VERBOSE
#define DEBUG(x) x
-#define CELL_DEBUG_SIZE(_cells,_i) \
- g_print ("Cell[%u] = { .cell = %p, .x = %d, .y = %d, .width = %d, .height = %d }\n", \
- _i, \
- _cells[_i].cell, \
- _cells[_i].cell_x, _cells[_i].cell_y, _cells[_i].cell_width, _cells[_i].cell_height)
#else
#define DEBUG(x)
-#define CELL_DEBUG_SIZE(cells,i)
#endif
typedef struct {
@@ -31,13 +36,9 @@ typedef struct {
gpointer sort_data;
GDestroyNotify sort_notify;
- GtkAdjustment *adjustment;
-
int cell_size;
int cell_spacing;
- int n_visible_children;
-
EosFlexyGridCell *prelight_cell;
EosFlexyGridCell *active_cell;
@@ -46,6 +47,16 @@ typedef struct {
enum
{
+ PROP_0,
+
+ PROP_CELL_SIZE,
+ PROP_CELL_SPACING,
+
+ LAST_PROP
+};
+
+enum
+{
CELL_SELECTED,
CELL_ACTIVATED,
@@ -69,32 +80,7 @@ G_DEFINE_TYPE (EosFlexyGrid, eos_flexy_grid, GTK_TYPE_CONTAINER)
#endif /* GLIB_CHECK_VERSION (2, 37, 5) */
static guint grid_signals[LAST_SIGNAL] = { 0, };
-
-static EosFlexyGridCell *
-eos_flexy_grid_get_cell_at_coords (EosFlexyGrid *grid,
- double x_pos,
- double y_pos)
-{
- EosFlexyGridPrivate *priv = grid->priv;
- GSequenceIter *iter;
-
- /* naive hit detection */
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter))
- {
- GtkWidget *widget = g_sequence_get (iter);
- GtkAllocation allocation;
-
- gtk_widget_get_allocation (widget, &allocation);
-
- if (x_pos >= allocation.x && x_pos < allocation.x + allocation.width &&
- y_pos >= allocation.y && y_pos < allocation.y + allocation.height)
- return EOS_FLEXY_GRID_CELL (widget);
- }
-
- return NULL;
-}
+static GParamSpec *grid_props[LAST_PROP] = { NULL, };
static void
eos_flexy_grid_update_cell_prelight (EosFlexyGrid *grid,
@@ -128,139 +114,278 @@ eos_flexy_grid_update_cell_prelight (EosFlexyGrid *grid,
gtk_widget_queue_draw (GTK_WIDGET (grid));
}
-typedef struct _CellRequest
+static inline void
+add_new_empty_line (GArray *array,
+ guint n_cols)
{
- EosFlexyGridCell *cell;
+ guint start = array->len;
- int cell_x;
- int cell_y;
- int cell_width;
- int cell_height;
-} CellRequest;
+ g_array_set_size (array, array->len + n_cols);
+ for (guint i = start; i < array->len; i++)
+ g_array_index (array, gboolean, i) = TRUE;
+}
-static inline void
-reset_cells (CellRequest *cells,
- guint n_cells)
+static guint
+get_next_free_slot (GArray *array,
+ guint pos,
+ guint n_cols)
{
- for (guint i = 0; i < n_cells; i++)
+ guint new_pos = pos;
+
+ if (new_pos >= array->len)
{
- cells[i].cell = NULL;
- cells[i].cell_x = 0;
- cells[i].cell_y = 0;
- cells[i].cell_width = 0;
- cells[i].cell_height = 0;
+ DEBUG (g_print ("Adding empty line to cover for %u\n", pos));
+ add_new_empty_line (array, n_cols);
}
-}
-static inline guint
-mark_cell (CellRequest *cells,
- guint n_cells,
- guint stride,
- guint index_,
- guint hspan,
- guint vspan,
- EosFlexyGridCell *cell)
-{
- guint i;
+ while (g_array_index (array, gboolean, new_pos) == FALSE)
+ {
+ new_pos += 1;
+ if (new_pos >= array->len)
+ add_new_empty_line (array, n_cols);
+ }
+
+ DEBUG (g_print ("Next free slot after %u: %u\n", pos, new_pos));
- cells[index_].cell = cell;
+ return new_pos;
+}
- i = 0;
- while (i++ < vspan - 1)
+static gboolean
+check_free_slot (GArray *array,
+ guint pos,
+ guint n_cols)
+{
+ while (pos >= array->len)
{
- DEBUG (g_print ("Marking vspan cell %u\n", index_ + (stride * i)));
- cells[index_ + (stride * i)].cell = cell;
+ DEBUG (g_print ("Adding empty line to cover for pos %u\n", pos));
+ add_new_empty_line (array, n_cols);
}
- i = 0;
- while (i++ < hspan - 1)
+ DEBUG (g_print ("Slot %u is %s\n", pos, g_array_index (array, gboolean, pos) ? "free" : "occupied"));
+
+ return g_array_index (array, gboolean, pos) == TRUE;
+}
+
+#define get_column(n_cols,pos) ((pos) % (n_cols))
+#define get_line(n_cols,pos) ((pos) / (n_cols))
+
+static inline void
+set_position (GtkAllocation *request,
+ guint n_cols,
+ guint pos,
+ guint cell_width,
+ guint spacing)
+{
+ guint width = cell_width + spacing;
+
+ request->y = get_line (n_cols, pos) * width;
+ request->x = get_column (n_cols, pos) * width;
+}
+
+static inline void
+mark_occupied_slot (GArray *array,
+ guint pos)
+{
+ g_array_index (array, gboolean, pos) = FALSE;
+}
+
+static guint
+allocate_small_cell (GArray *array,
+ guint n_cols,
+ guint pos,
+ guint cell_width,
+ guint spacing,
+ GtkAllocation *request)
+{
+ request->width = cell_width;
+ request->height = cell_width;
+
+ set_position (request, n_cols, pos, cell_width, spacing);
+ mark_occupied_slot (array, pos);
+
+ DEBUG (g_print ("1-Cell[%u (column %u of %u, line %u)] = { %d, %d - %d x %d }, next: %u\n",
+ pos, get_column (n_cols, pos), n_cols, get_line (n_cols, pos),
+ request->x,
+ request->y,
+ request->width,
+ request->height,
+ get_next_free_slot (array, pos, n_cols)));
+
+ return get_next_free_slot (array, pos, n_cols);
+}
+
+static guint
+allocate_medium_cell (GArray *array,
+ guint n_cols,
+ guint pos,
+ guint cell_width,
+ guint spacing,
+ GtkOrientation orientation,
+ GtkAllocation *request)
+{
+ guint check_pos = pos;
+ guint check_column = get_column (n_cols, check_pos);
+
+ switch (orientation)
{
- DEBUG (g_print ("Marking hspan cell %u\n", index_ + i));
- cells[index_ + i].cell = cell;
+ case GTK_ORIENTATION_HORIZONTAL:
+ request->width = 2 * cell_width + spacing;
+ request->height = cell_width;
+
+ /* two adjacent cells on the same line must be free */
+ while (!(check_column < (n_cols - 1) && check_free_slot (array, check_pos + 1, n_cols)))
+ {
+ check_pos += 1;
+ check_pos = get_next_free_slot (array, check_pos, n_cols);
+ check_column = get_column (n_cols, check_pos);
+ }
+
+ set_position (request, n_cols, check_pos, cell_width, spacing);
+ mark_occupied_slot (array, check_pos);
+ mark_occupied_slot (array, check_pos + 1);
+ break;
+
+ case GTK_ORIENTATION_VERTICAL:
+ request->width = cell_width;
+ request->height = 2 * cell_width + spacing;
+
+ /* two adjacent cells on the same column must be free */
+ while (!check_free_slot (array, check_pos + n_cols, n_cols))
+ {
+ check_pos += 1;
+ check_pos = get_next_free_slot (array, check_pos, n_cols);
+ check_column = get_column (n_cols, check_pos);
+ }
+
+ set_position (request, n_cols, check_pos, cell_width, spacing);
+ mark_occupied_slot (array, check_pos);
+ mark_occupied_slot (array, check_pos + n_cols);
+ break;
}
- guint next_slot = index_ + hspan;
- while (next_slot < n_cells)
- {
- DEBUG (g_print ("next_slot: %u (index_: %u + hspan: %u)\n", next_slot, index_, hspan));
- if (cells[next_slot].cell == NULL)
- break;
+ DEBUG (g_print ("2-Cell[%u (column %u of %u, line %u)] = { %d, %d - %d x %d }, next: %u\n",
+ pos, get_column (n_cols, pos), n_cols, get_line (n_cols, pos),
+ request->x,
+ request->y,
+ request->width,
+ request->height,
+ get_next_free_slot (array, pos, n_cols)));
+
+ return get_next_free_slot (array, pos, n_cols);
+}
- next_slot += 1;
+static guint
+allocate_large_cell (GArray *array,
+ guint n_cols,
+ guint pos,
+ guint cell_width,
+ guint spacing,
+ GtkAllocation *request)
+{
+ request->width = 2 * cell_width + spacing;
+ request->height = 2 * cell_width + spacing;
+
+ guint check_pos = pos;
+ guint check_column = get_column (n_cols, check_pos);
+
+ while (!(check_column < (n_cols - 1) &&
+ check_free_slot (array, check_pos + n_cols, n_cols) &&
+ check_free_slot (array, check_pos + 1, n_cols) &&
+ check_free_slot (array, check_pos + n_cols + 1, n_cols)))
+ {
+ check_pos += 1;
+ check_pos = get_next_free_slot (array, check_pos, n_cols);
+ check_column = get_column (n_cols, check_pos);
}
- return next_slot;
+ set_position (request, n_cols, check_pos, cell_width, spacing);
+ mark_occupied_slot (array, check_pos);
+ mark_occupied_slot (array, check_pos + 1);
+ mark_occupied_slot (array, check_pos + n_cols);
+ mark_occupied_slot (array, check_pos + n_cols + 1);
+
+ DEBUG (g_print ("4-Cell[%u (column %u of %u, line %u)] = { %d, %d - %d x %d }, next: %u\n",
+ pos, get_column (n_cols, pos), n_cols, get_line (n_cols, pos),
+ request->x,
+ request->y,
+ request->width,
+ request->height,
+ get_next_free_slot (array, pos, n_cols)));
+
+ return get_next_free_slot (array, pos, n_cols);
}
-static void
-eos_flexy_grid_distribute_cell_request (CellRequest *cells,
- guint n_cells,
- guint n_columns,
- EosFlexyGridCell *cell,
- guint cur_index,
- int cell_size,
- guint *next_index)
+static int
+distribute_layout (GSequence *children,
+ int available_width,
+ int cell_width,
+ int spacing,
+ gboolean allocate)
{
- EosFlexyShape cell_shape = eos_flexy_grid_cell_get_shape (cell);
+ guint n_columns = MAX (available_width / (cell_width + spacing), 2);
+ guint real_width = cell_width;
+ GArray *array = g_array_new (FALSE, FALSE, sizeof (gboolean));
+ guint current_pos = 0;
+ int max_height = cell_width;
- switch (cell_shape)
+ add_new_empty_line (array, n_columns);
+
+ GSequenceIter *iter;
+ for (iter = g_sequence_get_begin_iter (children);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
{
- case EOS_FLEXY_SHAPE_SMALL:
- /* b1 */
- cells[cur_index].cell_width = cell_size;
- cells[cur_index].cell_height = cell_size;
- cells[cur_index].cell_x = cur_index % n_columns * cell_size;
- cells[cur_index].cell_y = cur_index / n_columns * cell_size;
-
- *next_index = mark_cell (cells, n_cells, n_columns,
- cur_index,
- 1, 1,
- cell);
- CELL_DEBUG_SIZE (cells, cur_index);
- break;
+ EosFlexyGridCell *cell = g_sequence_get (iter);
+ EosFlexyShape shape = eos_flexy_grid_cell_get_shape (cell);
+ GtkAllocation request = { 0, };
- case EOS_FLEXY_SHAPE_MEDIUM_HORIZONTAL:
- /* b2h */
- cells[cur_index].cell_width = cell_size * 2;
- cells[cur_index].cell_height = cell_size;
- cells[cur_index].cell_x = cur_index % n_columns * cell_size;
- cells[cur_index].cell_y = cur_index / n_columns * cell_size;
-
- *next_index = mark_cell (cells, n_cells, n_columns,
- cur_index,
- 2, 1,
- cell);
- CELL_DEBUG_SIZE (cells, cur_index);
- break;
+ switch (shape)
+ {
+ case EOS_FLEXY_SHAPE_SMALL:
+ current_pos = allocate_small_cell (array,
+ n_columns, current_pos,
+ real_width, spacing,
+ &request);
+ break;
- case EOS_FLEXY_SHAPE_MEDIUM_VERTICAL:
- /* b2v */
- cells[cur_index].cell_width = cell_size;
- cells[cur_index].cell_height = cell_size * 2;
- cells[cur_index].cell_x = cur_index % n_columns * cell_size;
- cells[cur_index].cell_y = cur_index / n_columns * cell_size;
-
- *next_index = mark_cell (cells, n_cells, n_columns,
- cur_index,
- 1, 2,
- cell);
- CELL_DEBUG_SIZE (cells, cur_index);
- break;
+ case EOS_FLEXY_SHAPE_MEDIUM_HORIZONTAL:
+ current_pos = allocate_medium_cell (array,
+ n_columns, current_pos,
+ real_width, spacing,
+ GTK_ORIENTATION_HORIZONTAL,
+ &request);
+ break;
- case EOS_FLEXY_SHAPE_LARGE:
- /* b4 */
- cells[cur_index].cell_width = cell_size * 2;
- cells[cur_index].cell_height = cell_size * 2;
- cells[cur_index].cell_x = cur_index % n_columns * cell_size;
- cells[cur_index].cell_y = cur_index / n_columns * cell_size;
-
- *next_index = mark_cell (cells, n_cells, n_columns,
- cur_index,
- 2, 2,
- cell);
- CELL_DEBUG_SIZE (cells, cur_index);
- break;
+ case EOS_FLEXY_SHAPE_MEDIUM_VERTICAL:
+ current_pos = allocate_medium_cell (array,
+ n_columns, current_pos,
+ real_width, spacing,
+ GTK_ORIENTATION_VERTICAL,
+ &request);
+ break;
+
+ case EOS_FLEXY_SHAPE_LARGE:
+ current_pos = allocate_large_cell (array,
+ n_columns, current_pos,
+ real_width, spacing,
+ &request);
+ break;
+ }
+
+ max_height = MAX (max_height, request.y + request.height + spacing);
+
+ if (allocate)
+ gtk_widget_size_allocate (GTK_WIDGET (cell), &request);
}
+
+ g_array_unref (array);
+
+ DEBUG (g_print ("%s size: { %d x %d }\n",
+ allocate ? "Allocated" : "Preferred",
+ available_width,
+ max_height));
+
+ return max_height;
}
static GtkSizeRequestMode
@@ -345,80 +470,18 @@ eos_flexy_grid_get_preferred_height_for_width (GtkWidget *widget,
gint *natural_height_out)
{
EosFlexyGridPrivate *priv = EOS_FLEXY_GRID (widget)->priv;
- int minimum_height, natural_height;
int cell_size = priv->cell_size < 0 ? DEFAULT_CELL_SIZE : priv->cell_size;
+ int cell_spacing = priv->cell_spacing < 0 ? DEFAULT_SPACING : priv->cell_spacing;
+ int layout_height;
- /* minimum height: the maximum height of all the cells on a single row */
- minimum_height = cell_size * 2;
-
- int max_row_width = for_width;
- int row_width = 0, row_height = cell_size;
-
- int height = row_height;
- guint row = 1;
-
- /* natural width: the maximum width of all the cells on a single row */
- GSequenceIter *iter;
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter))
- {
- EosFlexyGridCell *cell = g_sequence_get (iter);
- int cell_height = 0, cell_width = 0;
-
- if (!gtk_widget_get_visible (GTK_WIDGET (cell)))
- continue;
-
- EosFlexyShape cell_shape = eos_flexy_grid_cell_get_shape (cell);
-
- switch (cell_shape)
- {
- case EOS_FLEXY_SHAPE_SMALL:
- /* b1 */
- cell_width = cell_size;
- cell_height = cell_size;
- break;
-
- case EOS_FLEXY_SHAPE_MEDIUM_HORIZONTAL:
- /* b2h */
- cell_width = cell_size * 2;
- cell_height = cell_size;
- break;
-
- case EOS_FLEXY_SHAPE_MEDIUM_VERTICAL:
- /* b2v */
- cell_width = cell_size;
- cell_height = cell_size * 2;
- break;
-
- case EOS_FLEXY_SHAPE_LARGE:
- /* b4 */
- cell_width = cell_size * 2;
- cell_height = cell_size * 2;
- break;
- }
-
- row_width += cell_width;
-
- if (row_width > max_row_width)
- {
- height = row * row_height;
-
- row += 1;
- row_width = cell_width;
- row_height = MAX (cell_height, cell_size);
- }
- else
- row_height = MAX (row_height, cell_height);
- }
-
- natural_height = MAX (height, cell_size);
+ layout_height = distribute_layout (priv->children, for_width, cell_size, cell_spacing, FALSE);
if (minimum_height_out)
- *minimum_height_out = minimum_height;
+ *minimum_height_out = layout_height;
+
if (natural_height_out)
- *natural_height_out = MAX (natural_height, minimum_height);
+ *natural_height_out = layout_height;
}
static void
@@ -448,58 +511,11 @@ eos_flexy_grid_size_allocate (GtkWidget *widget,
EosFlexyGridPrivate *priv = EOS_FLEXY_GRID (widget)->priv;
- int target_column_size = priv->cell_size < 0 ? DEFAULT_CELL_SIZE : priv->cell_size;
+ int cell_size = priv->cell_size < 0 ? DEFAULT_CELL_SIZE : priv->cell_size;
+ int cell_spacing = priv->cell_spacing < 0 ? DEFAULT_SPACING : priv->cell_spacing;
int available_width = allocation->width;
- int available_height = allocation->height;
- int cell_size = target_column_size;
- int n_columns = MAX (available_width / (cell_size + priv->cell_spacing), 2);
- int n_rows = MAX (available_height / (cell_size + priv->cell_spacing), 1);
-
- guint cur_index = 0, next_index = 0;
- guint n_cells = n_columns * n_rows;
- CellRequest *cells = g_newa (CellRequest, n_cells);
-
- reset_cells (cells, n_cells);
-
- DEBUG (g_print ("Size; %d x %d (cols: %u, rows: %u)\n",
- available_width, available_height,
- n_columns,
- n_rows));
-
- GSequenceIter *iter;
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter))
- {
- EosFlexyGridCell *cell = g_sequence_get (iter);
- GtkAllocation child_allocation;
-
- if (!gtk_widget_get_visible (GTK_WIDGET (cell)))
- continue;
-
- if (cur_index > n_cells)
- break;
-
- eos_flexy_grid_distribute_cell_request (cells, n_cells, n_columns,
- cell,
- cur_index,
- cell_size,
- &next_index);
-
- child_allocation.x = cells[cur_index].cell_x + priv->cell_spacing;
- child_allocation.y = cells[cur_index].cell_y + priv->cell_spacing;
- child_allocation.width = cells[cur_index].cell_width - priv->cell_spacing;
- child_allocation.height = cells[cur_index].cell_height - priv->cell_spacing;
-
- gtk_widget_size_allocate (GTK_WIDGET (cell), &child_allocation);
- DEBUG (g_print ("cur_index: %u, next_index: %u, column: %d, row: %d\n",
- cur_index, next_index,
- cur_index % n_columns,
- cur_index / n_columns));
-
- cur_index = next_index;
- }
+ distribute_layout (priv->children, available_width, cell_size, cell_spacing, TRUE);
}
static void
@@ -771,6 +787,52 @@ eos_flexy_grid_leave_notify (GtkWidget *widget,
}
static void
+eos_flexy_grid_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EosFlexyGrid *self = EOS_FLEXY_GRID (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_CELL_SIZE:
+ eos_flexy_grid_set_cell_size (self, g_value_get_int (value));
+ break;
+
+ case PROP_CELL_SPACING:
+ eos_flexy_grid_set_cell_spacing (self, g_value_get_int (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+eos_flexy_grid_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EosFlexyGrid *self = EOS_FLEXY_GRID (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_CELL_SIZE:
+ g_value_set_int (value, eos_flexy_grid_get_cell_size (self));
+ break;
+
+ case PROP_CELL_SPACING:
+ g_value_set_int (value, eos_flexy_grid_get_cell_spacing (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
eos_flexy_grid_finalize (GObject *gobject)
{
EosFlexyGridPrivate *priv = EOS_FLEXY_GRID (gobject)->priv;
@@ -778,8 +840,6 @@ eos_flexy_grid_finalize (GObject *gobject)
if (priv->sort_notify != NULL)
priv->sort_notify (priv->sort_data);
- g_clear_object (&priv->adjustment);
-
g_sequence_free (priv->children);
G_OBJECT_CLASS (eos_flexy_grid_parent_class)->finalize (gobject);
@@ -794,6 +854,8 @@ eos_flexy_grid_class_init (EosFlexyGridClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = eos_flexy_grid_finalize;
+ gobject_class->set_property = eos_flexy_grid_set_property;
+ gobject_class->get_property = eos_flexy_grid_get_property;
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->get_request_mode = eos_flexy_grid_get_request_mode;
@@ -816,6 +878,42 @@ eos_flexy_grid_class_init (EosFlexyGridClass *klass)
container_class->forall = eos_flexy_grid_forall;
container_class->child_type = eos_flexy_grid_child_type;
+ /**
+ * EosFlexyGrid:cell-size:
+ *
+ * The minimum size of each cell inside a #EosFlexyGrid, or -1 for the default.
+ */
+ grid_props[PROP_CELL_SIZE] =
+ g_param_spec_int ("cell-size",
+ "Cell Size",
+ "The minimum size of each cell",
+ -1, G_MAXINT,
+ -1,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * EosFlexyGrid:cell-spacing:
+ *
+ * The spacing between each cell inside a #EosFlexyGrid, or -1 for the default.
+ */
+ grid_props[PROP_CELL_SPACING] =
+ g_param_spec_int ("cell-spacing",
+ "Cell Spacing",
+ "The spacing between each cell",
+ -1, G_MAXINT,
+ -1,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, LAST_PROP, grid_props);
+
+ /**
+ * EosFlexyGrid::cell-selected:
+ * @grid: the #EosFlexyGrid that emitted the signal
+ * @cell: the #EosFlexyGridCell that was selected
+ *
+ * The ::cell-selected signal is emitted each time a cell inside @grid
+ * is selected. Selection happens by hovering on a cell.
+ */
grid_signals[CELL_SELECTED] =
g_signal_new (g_intern_static_string ("cell-selected"),
EOS_TYPE_FLEXY_GRID,
@@ -826,6 +924,14 @@ eos_flexy_grid_class_init (EosFlexyGridClass *klass)
G_TYPE_NONE, 1,
EOS_TYPE_FLEXY_GRID_CELL);
+ /**
+ * EosFlexyGrid::cell-activated:
+ * @grid: the #EosFlexyGrid that emitted the signal
+ * @cell: the #EosFlexyGridCell that was activated
+ *
+ * The ::cell-activated signal is emitted each time a cell inside @grid
+ * is activated. Activation happens by clicking on a cell.
+ */
grid_signals[CELL_ACTIVATED] =
g_signal_new (g_intern_static_string ("cell-activated"),
EOS_TYPE_FLEXY_GRID,
@@ -859,12 +965,39 @@ eos_flexy_grid_init (EosFlexyGrid *self)
gtk_style_context_add_class (context, EOS_STYLE_CLASS_FLEXY_GRID);
}
+/**
+ * eos_flexy_grid_new:
+ *
+ * Creates a new #EosFlexyGrid widget.
+ *
+ * Return value: (transfer full): the newly created #EosFlexyGrid widget
+ */
GtkWidget *
eos_flexy_grid_new (void)
{
return g_object_new (EOS_TYPE_FLEXY_GRID, NULL);
}
+/**
+ * eos_flexy_grid_set_sort_func:
+ * @grid: a #EosFlexyGrid
+ * @sort_func: (scope notified) (allow-none): a sorting function, or
+ * %NULL to unset an existing one
+ * @data: (closure): data to pass to @sort_func and @notify
+ * @notify: function called when @sort_func is unset, or the @grid
+ * widget is destroyed
+ *
+ * Sets the sorting function for @grid.
+ *
+ * The @sort_func function compares two children of @grid, and must
+ * return -1 if the first child should precede the second; 1, if the
+ * first child should follow the second; or 0, if the children are
+ * identical.
+ *
+ * The @notify function will be called when this function is called
+ * with a different @sort_func (or %NULL); or when the @grid widget
+ * is destroyed.
+ */
void
eos_flexy_grid_set_sort_func (EosFlexyGrid *grid,
EosFlexyGridSortFunc sort_func,
@@ -882,6 +1015,15 @@ eos_flexy_grid_set_sort_func (EosFlexyGrid *grid,
priv->sort_notify = notify;
}
+/**
+ * eos_flexy_grid_set_cell_size:
+ * @grid: a #EosFlexyGrid
+ * @size: the size of the cell
+ *
+ * Sets the size of the cells of @grid.
+ *
+ * If @size is less than 0, the default size will be used.
+ */
void
eos_flexy_grid_set_cell_size (EosFlexyGrid *grid,
int size)
@@ -897,6 +1039,36 @@ eos_flexy_grid_set_cell_size (EosFlexyGrid *grid,
gtk_widget_queue_resize (GTK_WIDGET (grid));
}
+/**
+ * eos_flexy_grid_get_cell_size:
+ * @grid: a #EosFlexyGrid
+ *
+ * Retrieves the size of the cells of @grid.
+ *
+ * Return value: the size of the cells
+ */
+guint
+eos_flexy_grid_get_cell_size (EosFlexyGrid *grid)
+{
+ g_return_val_if_fail (EOS_IS_FLEXY_GRID (grid), 0);
+
+ EosFlexyGridPrivate *priv = grid->priv;
+
+ if (priv->cell_size < 0)
+ return DEFAULT_CELL_SIZE;
+
+ return priv->cell_size;
+}
+
+/**
+ * eos_flexy_grid_set_cell_spacing:
+ * @grid: a #EosFlexyGrid
+ * @spacing: the spacing between each cell
+ *
+ * Sets the spacing between each cell of @grid.
+ *
+ * If @spacing is less than 0, the default value will be used.
+ */
void
eos_flexy_grid_set_cell_spacing (EosFlexyGrid *grid,
int spacing)
@@ -912,6 +1084,27 @@ eos_flexy_grid_set_cell_spacing (EosFlexyGrid *grid,
gtk_widget_queue_resize (GTK_WIDGET (grid));
}
+/**
+ * eos_flexy_grid_get_cell_spacing:
+ * @grid: a #EosFlexyGrid
+ *
+ * Retrieves the cell spacing of @grid.
+ *
+ * Return value: the spacing between each cell
+ */
+guint
+eos_flexy_grid_get_cell_spacing (EosFlexyGrid *grid)
+{
+ g_return_val_if_fail (EOS_IS_FLEXY_GRID (grid), 0);
+
+ EosFlexyGridPrivate *priv = grid->priv;
+
+ if (priv->cell_spacing < 0)
+ return DEFAULT_SPACING;
+
+ return priv->cell_spacing;
+}
+
static gint
do_grid_sort (gconstpointer row_a,
gconstpointer row_b,
@@ -924,6 +1117,22 @@ do_grid_sort (gconstpointer row_a,
priv->sort_data);
}
+/**
+ * eos_flexy_grid_insert:
+ * @grid: a #EosFlexyGrid
+ * @child: a #GtkWidget
+ * @index_: the position of the @child
+ *
+ * Inserts @child inside @grid, at the given @index_. If @child is not
+ * a #EosFlexyGridCell widget, one will be implicitly created, and @child
+ * added to it.
+ *
+ * If @grid has a sort function, the @index_ is ignored.
+ *
+ * If @index_ is less than 0, the @child is appended at the end of the grid.
+ *
+ * If @index_ is 0, the child is prepended at the beginning of the grid.
+ */
void
eos_flexy_grid_insert (EosFlexyGrid *grid,
GtkWidget *child,
@@ -968,3 +1177,44 @@ eos_flexy_grid_insert (EosFlexyGrid *grid,
gtk_widget_set_parent (GTK_WIDGET (cell), GTK_WIDGET (grid));
gtk_widget_set_child_visible (GTK_WIDGET (cell), TRUE);
}
+
+/**
+ * eos_flexy_grid_get_cell_at_coords:
+ * @grid: a #EosFlexyGrid
+ * @x_pos: X coordinate to test, in widget-relative space
+ * @y_pos: Y coordinate to test, in widget-relative space
+ *
+ * Retrieves the #EosFlexyGridCell at the given coordinates.
+ *
+ * The coordinates to test must be in widget-relative space.
+ *
+ * Return value: (transfer none): the cell at the given coordinates, or %NULL
+ */
+EosFlexyGridCell *
+eos_flexy_grid_get_cell_at_coords (EosFlexyGrid *grid,
+ double x_pos,
+ double y_pos)
+{
+ g_return_val_if_fail (EOS_IS_FLEXY_GRID (grid), NULL);
+
+ EosFlexyGridPrivate *priv = grid->priv;
+ GSequenceIter *iter;
+
+ /* naive hit detection */
+ for (iter = g_sequence_get_begin_iter (priv->children);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
+ {
+ GtkWidget *widget = g_sequence_get (iter);
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ if (x_pos >= allocation.x && x_pos < allocation.x + allocation.width &&
+ y_pos >= allocation.y && y_pos < allocation.y + allocation.height)
+ return EOS_FLEXY_GRID_CELL (widget);
+ }
+
+ return NULL;
+}
+
diff --git a/endless/eosflexygrid.h b/endless/eosflexygrid.h
index 6a11f78..f1d9516 100644
--- a/endless/eosflexygrid.h
+++ b/endless/eosflexygrid.h
@@ -61,22 +61,30 @@ EOS_SDK_ALL_API_VERSIONS
GType eos_flexy_grid_get_type (void) G_GNUC_CONST;
EOS_SDK_ALL_API_VERSIONS
-GtkWidget * eos_flexy_grid_new (void);
+GtkWidget * eos_flexy_grid_new (void);
EOS_SDK_ALL_API_VERSIONS
-void eos_flexy_grid_set_cell_size (EosFlexyGrid *grid,
- int size);
+void eos_flexy_grid_set_cell_size (EosFlexyGrid *grid,
+ int size);
EOS_SDK_ALL_API_VERSIONS
-void eos_flexy_grid_set_cell_spacing (EosFlexyGrid *grid,
- int spacing);
+guint eos_flexy_grid_get_cell_size (EosFlexyGrid *grid);
EOS_SDK_ALL_API_VERSIONS
-void eos_flexy_grid_insert (EosFlexyGrid *grid,
- GtkWidget *child,
- int index_);
+void eos_flexy_grid_set_cell_spacing (EosFlexyGrid *grid,
+ int spacing);
EOS_SDK_ALL_API_VERSIONS
-void eos_flexy_grid_set_sort_func (EosFlexyGrid *grid,
- EosFlexyGridSortFunc sort_func,
- gpointer data,
- GDestroyNotify notify);
+guint eos_flexy_grid_get_cell_spacing (EosFlexyGrid *grid);
+EOS_SDK_ALL_API_VERSIONS
+void eos_flexy_grid_insert (EosFlexyGrid *grid,
+ GtkWidget *child,
+ int index_);
+EOS_SDK_ALL_API_VERSIONS
+void eos_flexy_grid_set_sort_func (EosFlexyGrid *grid,
+ EosFlexyGridSortFunc sort_func,
+ gpointer data,
+ GDestroyNotify notify);
+EOS_SDK_ALL_API_VERSIONS
+EosFlexyGridCell * eos_flexy_grid_get_cell_at_coords (EosFlexyGrid *grid,
+ double x_pos,
+ double y_pos);
struct _EosFlexyGridCell
{
diff --git a/endless/eosflexygridcell.c b/endless/eosflexygridcell.c
index 4cc2627..4091f06 100644
--- a/endless/eosflexygridcell.c
+++ b/endless/eosflexygridcell.c
@@ -98,6 +98,11 @@ eos_flexy_grid_cell_class_init (EosFlexyGridCellClass *klass)
gobject_class->set_property = eos_flexy_grid_cell_set_property;
gobject_class->get_property = eos_flexy_grid_cell_get_property;
+ /**
+ * EosFlexyGridCell:shape:
+ *
+ * The shape of the cell.
+ */
obj_props[PROP_SHAPE] =
g_param_spec_enum ("shape",
"Shape",
@@ -123,12 +128,27 @@ eos_flexy_grid_cell_init (EosFlexyGridCell *self)
gtk_style_context_add_class (context, EOS_STYLE_CLASS_FLEXY_GRID_CELL);
}
+/**
+ * eos_flexy_grid_cell_new:
+ *
+ * Creates a new #EosFlexyGridCell widget.
+ *
+ * Return value: (transfer full): the newly created #EosFlexyGridCell widget
+ */
GtkWidget *
eos_flexy_grid_cell_new (void)
{
return g_object_new (EOS_TYPE_FLEXY_GRID_CELL, NULL);
}
+/**
+ * eos_flexy_grid_cell_set_shape:
+ * @cell: a #EosFlexyGridCell
+ * @shape: the shape of the cell
+ *
+ * Sets the shape of the @cell. The @shape determines the amount of
+ * space inside a #EosFlexyGrid that will be assigned to the @cell.
+ */
void
eos_flexy_grid_cell_set_shape (EosFlexyGridCell *cell,
EosFlexyShape shape)
@@ -143,9 +163,19 @@ eos_flexy_grid_cell_set_shape (EosFlexyGridCell *cell,
priv->shape = shape;
g_object_notify_by_pspec (G_OBJECT (cell), obj_props[PROP_SHAPE]);
+
+ gtk_widget_queue_resize (GTK_WIDGET (cell));
}
}
+/**
+ * eos_flexy_grid_cell_get_shape:
+ * @cell: a #EosFlexyGridCell
+ *
+ * Retrieves the shape of @cell.
+ *
+ * Return value: the shape of the #EosFlexyGridCell
+ */
EosFlexyShape
eos_flexy_grid_cell_get_shape (EosFlexyGridCell *cell)
{
@@ -158,7 +188,13 @@ eos_flexy_grid_cell_get_shape (EosFlexyGridCell *cell)
return priv->shape;
}
-/*< private >*/
+/*< private >
+ * eos_flexy_grid_cell_set_iter:
+ * @cell: a #EosFlexyGridCell
+ * @iter: a #GSequenceIter
+ *
+ * The #GSequenceIter associated to @cell.
+ */
void
eos_flexy_grid_cell_set_iter (EosFlexyGridCell *cell,
GSequenceIter *iter)
@@ -168,7 +204,14 @@ eos_flexy_grid_cell_set_iter (EosFlexyGridCell *cell,
priv->iter = iter;
}
-/*< private >*/
+/*< private >
+ * eos_flexy_grid_cell_get_iter:
+ * @cell: a #EosFlexyGridCell
+ *
+ * Retrieves the #GSequenceIter associated to @cell.
+ *
+ * Return value: (transfer none): a #GSequenceIter
+ */
GSequenceIter *
eos_flexy_grid_cell_get_iter (EosFlexyGridCell *cell)
{
@@ -177,7 +220,13 @@ eos_flexy_grid_cell_get_iter (EosFlexyGridCell *cell)
return priv->iter;
}
-/*< private >*/
+/*< private >
+ * eos_flexy_grid_cell_set_selected:
+ * @cell: a #EosFlexyGridCell
+ * @selected: %TRUE to select the @cell, and %FALSE otherwise
+ *
+ * Sets whether the @cell should be selected or not.
+ */
void
eos_flexy_grid_cell_set_selected (EosFlexyGridCell *cell,
gboolean selected)
@@ -193,6 +242,15 @@ eos_flexy_grid_cell_set_selected (EosFlexyGridCell *cell,
}
}
+/**
+ * eos_flexy_grid_cell_get_selected:
+ * @cell: a #EosFlexyGridCell
+ *
+ * Checks whether @cell is selected.
+ *
+ * Return value: %TRUE if the #EosFlexyGridCell is selected,
+ * and %FALSE otherwise
+ */
gboolean
eos_flexy_grid_cell_get_selected (EosFlexyGridCell *cell)
{
diff --git a/test/Makefile.am b/test/Makefile.am
index 4124c52..4730b8b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,6 +2,7 @@
noinst_PROGRAMS = \
test/run-tests \
+ test/flexy-grid \
test/smoke-tests/hello
TEST_FLAGS = @EOS_SDK_CFLAGS@ -I$(top_srcdir) -DCOMPILING_EOS_SDK
@@ -17,6 +18,7 @@ test_run_tests_SOURCES = \
test/test-window.c \
test/test-action-menu.c \
test/test-action-button.c \
+ test/test-flexy-grid.c \
$(NULL)
test_run_tests_CPPFLAGS = $(TEST_FLAGS)
test_run_tests_LDADD = $(TEST_LIBS)
@@ -25,6 +27,10 @@ test_smoke_tests_hello_SOURCES = test/smoke-tests/hello.c
test_smoke_tests_hello_CPPFLAGS = $(TEST_FLAGS)
test_smoke_tests_hello_LDADD = $(TEST_LIBS)
+test_flexy_grid_SOURCES = test/flexy-grid.c
+test_flexy_grid_CPPFLAGS = $(TEST_FLAGS)
+test_flexy_grid_LDADD = $(TEST_LIBS)
+
javascript_tests = \
test/tools/eos-run-test/sanitycheck.js \
test/webhelper/testTranslate.js \
diff --git a/test/flexy-grid.c b/test/flexy-grid.c
new file mode 100644
index 0000000..2008af4
--- /dev/null
+++ b/test/flexy-grid.c
@@ -0,0 +1,107 @@
+#include <endless/endless.h>
+
+static const char *icons[] = {
+ "applications-accessories",
+ "applications-development",
+ "applications-engineering",
+ "applications-games",
+ "applications-graphics",
+ "applications-internet",
+ "applications-multimedia",
+ "applications-office",
+ "applications-other",
+ "applications-science",
+ "applications-system",
+ "applications-utilities",
+};
+
+#define CHAR(r,g,b) { r / 255.0, g / 255.0, b / 255.0, 1.0 }
+
+static GdkRGBA colors[] = {
+ CHAR (0xff, 0x00, 0x00),
+ CHAR (0x80, 0x00, 0x00),
+ CHAR (0x00, 0xff, 0x00),
+ CHAR (0x00, 0x80, 0x00),
+ CHAR (0x00, 0x00, 0xff),
+ CHAR (0x00, 0x00, 0x80),
+ CHAR (0x00, 0xff, 0xff),
+ CHAR (0x00, 0x80, 0x80),
+ CHAR (0xff, 0x00, 0xff),
+ CHAR (0x80, 0x00, 0x80),
+ CHAR (0xff, 0xff, 0x00),
+ CHAR (0x80, 0x80, 0x00),
+ CHAR (0xa0, 0xa0, 0xa4),
+ CHAR (0x80, 0x80, 0x80),
+ CHAR (0xc0, 0xc0, 0xc0),
+};
+
+static EosFlexyShape shapes[] = {
+ EOS_FLEXY_SHAPE_MEDIUM_HORIZONTAL,
+ EOS_FLEXY_SHAPE_MEDIUM_VERTICAL,
+ EOS_FLEXY_SHAPE_SMALL,
+ EOS_FLEXY_SHAPE_SMALL,
+ EOS_FLEXY_SHAPE_SMALL,
+ EOS_FLEXY_SHAPE_MEDIUM_VERTICAL,
+ EOS_FLEXY_SHAPE_MEDIUM_HORIZONTAL,
+ EOS_FLEXY_SHAPE_SMALL,
+};
+
+static void
+on_cell_selected (EosFlexyGrid *grid, EosFlexyGridCell *cell)
+{
+ g_print ("Cell %p selected\n", cell);
+}
+
+static void
+on_cell_activated (EosFlexyGrid *grid, EosFlexyGridCell *cell)
+{
+ g_print ("Cell %p activated\n", cell);
+}
+
+int
+main (int argc, char *argv[])
+{
+ gtk_init (NULL, NULL);
+
+ GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ gtk_widget_show (window);
+
+ GtkWidget *scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (window), scroll);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_show (scroll);
+
+ GtkWidget *grid = eos_flexy_grid_new ();
+ g_signal_connect (grid, "cell-selected", G_CALLBACK (on_cell_selected), NULL);
+ g_signal_connect (grid, "cell-activated", G_CALLBACK (on_cell_activated), NULL);
+ gtk_container_add (GTK_CONTAINER (scroll), grid);
+ gtk_widget_show (grid);
+
+ for (guint i = 0; i < 8; i++)
+ {
+ GtkWidget *cell = eos_flexy_grid_cell_new ();
+ eos_flexy_grid_cell_set_shape (EOS_FLEXY_GRID_CELL (cell), shapes[i]);
+ gtk_container_add (GTK_CONTAINER (grid), cell);
+ gtk_widget_show (cell);
+
+ GtkWidget *frame = gtk_event_box_new ();
+ gtk_widget_override_background_color (frame, GTK_STATE_FLAG_NORMAL, &colors[i]);
+ gtk_container_add (GTK_CONTAINER (cell), frame);
+ gtk_widget_show (frame);
+
+ GtkWidget *image = gtk_image_new ();
+ gtk_image_set_from_icon_name (GTK_IMAGE (image), icons[i], GTK_ICON_SIZE_DIALOG);
+ gtk_container_add (GTK_CONTAINER (frame), image);
+ gtk_widget_set_hexpand (image, TRUE);
+ gtk_widget_set_vexpand (image, TRUE);
+ gtk_widget_show (image);
+ }
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/test/run-tests.c b/test/run-tests.c
index 2e36212..b73d520 100644
--- a/test/run-tests.c
+++ b/test/run-tests.c
@@ -94,6 +94,7 @@ main (int argc,
add_splash_page_manager_tests ();
add_action_menu_tests ();
add_action_button_tests ();
+ add_flexy_grid_test ();
return g_test_run ();
}
diff --git a/test/run-tests.h b/test/run-tests.h
index 42cadf5..88a57d5 100644
--- a/test/run-tests.h
+++ b/test/run-tests.h
@@ -39,5 +39,6 @@ void add_page_manager_tests (void);
void add_splash_page_manager_tests (void);
void add_action_menu_tests (void);
void add_action_button_tests (void);
+void add_flexy_grid_test (void);
#endif /* RUN_TESTS_H */
diff --git a/test/test-flexy-grid.c b/test/test-flexy-grid.c
new file mode 100644
index 0000000..0c6c3cc
--- /dev/null
+++ b/test/test-flexy-grid.c
@@ -0,0 +1,75 @@
+#include <gtk/gtk.h>
+#include <endless/endless.h>
+
+#include <endless/eosflexygrid-private.h>
+
+#include "run-tests.h"
+
+typedef struct
+{
+ EosFlexyGrid *grid;
+} FlexyGridFixture;
+
+#define ADD_FLEXY_GRID_TEST(path, test_func) \
+ g_test_add ((path), FlexyGridFixture, NULL, \
+ flexy_grid_fixture_setup, \
+ (test_func), \
+ flexy_grid_fixture_teardown)
+
+
+static void
+flexy_grid_fixture_setup (FlexyGridFixture *fixture,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ fixture->grid = (EosFlexyGrid *) eos_flexy_grid_new ();
+}
+
+static void
+flexy_grid_fixture_teardown (FlexyGridFixture *fixture,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ gtk_widget_destroy ((GtkWidget *) fixture->grid);
+}
+
+static void
+flexy_grid_cell_size_access (FlexyGridFixture *fixture,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ eos_flexy_grid_set_cell_size (fixture->grid, 6);
+ g_assert_cmpint (eos_flexy_grid_get_cell_size (fixture->grid), ==, 6);
+
+ eos_flexy_grid_set_cell_size (fixture->grid, -1);
+ g_assert_cmpint (eos_flexy_grid_get_cell_size (fixture->grid), !=, -1);
+
+ int cell_size = 0;
+ g_object_get (fixture->grid, "cell-size", &cell_size, NULL);
+ g_assert_cmpint (cell_size, !=, -1);
+
+ g_object_set (fixture->grid, "cell-size", 250, NULL);
+ g_assert_cmpint (eos_flexy_grid_get_cell_size (fixture->grid), ==, 250);
+}
+
+static void
+flexy_grid_cell_spacing_access (FlexyGridFixture *fixture,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ eos_flexy_grid_set_cell_spacing (fixture->grid, 6);
+ g_assert_cmpint (eos_flexy_grid_get_cell_spacing (fixture->grid), ==, 6);
+
+ eos_flexy_grid_set_cell_spacing (fixture->grid, -1);
+ g_assert_cmpint (eos_flexy_grid_get_cell_spacing (fixture->grid), !=, -1);
+
+ int cell_spacing = 0;
+ g_object_get (fixture->grid, "cell-spacing", &cell_spacing, NULL);
+ g_assert_cmpint (cell_spacing, !=, -1);
+
+ g_object_set (fixture->grid, "cell-spacing", 12, NULL);
+ g_assert_cmpint (eos_flexy_grid_get_cell_spacing (fixture->grid), ==, 12);
+}
+
+void
+add_flexy_grid_test (void)
+{
+ ADD_FLEXY_GRID_TEST ("/flexy-grid/get-set-cell-size", flexy_grid_cell_size_access);
+ ADD_FLEXY_GRID_TEST ("/flexy-grid/get-set-cell-spacing", flexy_grid_cell_spacing_access);
+}