summaryrefslogtreecommitdiff
path: root/endless
diff options
context:
space:
mode:
Diffstat (limited to 'endless')
-rw-r--r--endless/eosflexygrid.c284
-rw-r--r--endless/eosflexygrid.h32
2 files changed, 278 insertions, 38 deletions
diff --git a/endless/eosflexygrid.c b/endless/eosflexygrid.c
index a686898..740290e 100644
--- a/endless/eosflexygrid.c
+++ b/endless/eosflexygrid.c
@@ -1,5 +1,15 @@
/* Copyright 2013 Endless Mobile, Inc. */
+/**
+ * SECTION:eos-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"
@@ -37,6 +47,16 @@ typedef struct {
enum
{
+ PROP_0,
+
+ PROP_CELL_SIZE,
+ PROP_CELL_SPACING,
+
+ LAST_PROP
+};
+
+enum
+{
CELL_SELECTED,
CELL_ACTIVATED,
@@ -60,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,
@@ -795,6 +790,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;
@@ -816,6 +857,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;
@@ -838,6 +881,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,
@@ -848,6 +927,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,
@@ -881,12 +968,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 notify) (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,
@@ -904,6 +1018,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)
@@ -919,6 +1042,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)
@@ -934,6 +1087,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,
@@ -946,6 +1120,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,
@@ -990,3 +1180,45 @@ 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);
+ 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
{