[clutter/clutter-1.16] flow-layout: Add :snap-to-grid property



commit cd9ba0ad8de7f01aae7353aba5ff0d209510e118
Author: Bastian Winkler <buz netbuz org>
Date:   Fri May 3 11:53:44 2013 -0400

    flow-layout: Add :snap-to-grid property
    
    Add a :snap-to-grid property to FlowLayout to prevent the layout from
    assigning it's children a position based on the size of the largest
    child.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=648873

 clutter/clutter-flow-layout.c              |  206 ++++++++++++++++++++++------
 clutter/clutter-flow-layout.h              |    5 +
 clutter/clutter.symbols                    |    2 +
 doc/reference/clutter/clutter-sections.txt |    2 +
 examples/flow-layout.c                     |   10 ++
 5 files changed, 182 insertions(+), 43 deletions(-)
---
diff --git a/clutter/clutter-flow-layout.c b/clutter/clutter-flow-layout.c
index 97524b2..094c552 100644
--- a/clutter/clutter-flow-layout.c
+++ b/clutter/clutter-flow-layout.c
@@ -113,6 +113,7 @@ struct _ClutterFlowLayoutPrivate
   guint line_count;
 
   guint is_homogeneous : 1;
+  guint snap_to_grid : 1;
 };
 
 enum
@@ -131,6 +132,8 @@ enum
   PROP_MIN_ROW_HEGHT,
   PROP_MAX_ROW_HEIGHT,
 
+  PROP_SNAP_TO_GRID,
+
   N_PROPERTIES
 };
 
@@ -258,7 +261,12 @@ clutter_flow_layout_get_preferred_width (ClutterLayoutManager *manager,
 
       if (priv->orientation == CLUTTER_FLOW_VERTICAL && for_height > 0)
         {
-          if (line_item_count == n_rows)
+          clutter_actor_get_preferred_height (child, -1,
+                                              &child_min,
+                                              &child_natural);
+
+          if ((priv->snap_to_grid && line_item_count == n_rows) ||
+              (!priv->snap_to_grid && item_y + child_natural > for_height))
             {
               total_min_width += line_min_width;
               total_natural_width += line_natural_width;
@@ -275,9 +283,17 @@ clutter_flow_layout_get_preferred_width (ClutterLayoutManager *manager,
               item_y = 0;
             }
 
-          new_y = ((line_item_count + 1) * (for_height + priv->row_spacing))
-                / n_rows;
-          item_height = new_y - item_y - priv->row_spacing;
+          if (priv->snap_to_grid)
+            {
+              new_y = ((line_item_count + 1) * (for_height + priv->row_spacing))
+                    / n_rows;
+              item_height = new_y - item_y - priv->row_spacing;
+            }
+          else
+            {
+              new_y = item_y + child_natural + priv->row_spacing;
+              item_height = child_natural;
+            }
 
           clutter_actor_get_preferred_width (child, item_height,
                                              &child_min,
@@ -436,7 +452,12 @@ clutter_flow_layout_get_preferred_height (ClutterLayoutManager *manager,
 
       if (priv->orientation == CLUTTER_FLOW_HORIZONTAL && for_width > 0)
         {
-          if (line_item_count == n_columns)
+          clutter_actor_get_preferred_width (child, -1,
+                                             &child_min,
+                                             &child_natural);
+
+          if ((priv->snap_to_grid && line_item_count == n_columns) ||
+              (!priv->snap_to_grid && item_x + child_natural > for_width))
             {
               total_min_height += line_min_height;
               total_natural_height += line_natural_height;
@@ -453,9 +474,17 @@ clutter_flow_layout_get_preferred_height (ClutterLayoutManager *manager,
               item_x = 0;
             }
 
-          new_x = ((line_item_count + 1) * (for_width + priv->col_spacing))
-                / n_columns;
-          item_width = new_x - item_x - priv->col_spacing;
+          if (priv->snap_to_grid)
+            {
+              new_x = ((line_item_count + 1) * (for_width + priv->col_spacing))
+                    / n_columns;
+              item_width = new_x - item_x - priv->col_spacing;
+            }
+          else
+            {
+              new_x = item_x + child_natural + priv->col_spacing;
+              item_width = child_natural;
+            }
 
           clutter_actor_get_preferred_height (child, item_width,
                                               &child_min,
@@ -606,15 +635,24 @@ clutter_flow_layout_allocate (ClutterLayoutManager   *manager,
       ClutterActorBox child_alloc;
       gfloat item_width, item_height;
       gfloat new_x, new_y;
+      gfloat child_min, child_natural;
 
       if (!CLUTTER_ACTOR_IS_VISIBLE (child))
         continue;
 
       new_x = new_y = 0;
 
+      if (!priv->snap_to_grid)
+        clutter_actor_get_preferred_size (child,
+                                          NULL, NULL,
+                                          &item_width,
+                                          &item_height);
+
       if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
         {
-          if (line_item_count == items_per_line && line_item_count > 0)
+          if ((priv->snap_to_grid &&
+               line_item_count == items_per_line && line_item_count > 0) ||
+              (!priv->snap_to_grid && item_x + item_width > avail_width))
             {
               item_y += g_array_index (priv->line_natural,
                                        gfloat,
@@ -629,31 +667,27 @@ clutter_flow_layout_allocate (ClutterLayoutManager   *manager,
               item_x = x_off;
             }
 
-          new_x = x_off + ((line_item_count + 1) * (avail_width + priv->col_spacing))
-                / items_per_line;
-          item_width = new_x - item_x - priv->col_spacing;
+          if (priv->snap_to_grid)
+            {
+              new_x = x_off + ((line_item_count + 1) * (avail_width + priv->col_spacing))
+                    / items_per_line;
+              item_width = new_x - item_x - priv->col_spacing;
+            }
+          else
+            {
+              new_x = item_x + item_width + priv->col_spacing;
+            }
+
           item_height = g_array_index (priv->line_natural,
                                        gfloat,
                                        line_index);
 
-          if (!priv->is_homogeneous)
-            {
-              gfloat child_min, child_natural;
-
-              clutter_actor_get_preferred_width (child, item_height,
-                                                 &child_min,
-                                                 &child_natural);
-              item_width = MIN (item_width, child_natural);
-
-              clutter_actor_get_preferred_height (child, item_width,
-                                                  &child_min,
-                                                  &child_natural);
-              item_height = MIN (item_height, child_natural);
-            }
         }
       else
         {
-          if (line_item_count == items_per_line && line_item_count > 0)
+          if ((priv->snap_to_grid &&
+               line_item_count == items_per_line && line_item_count > 0) ||
+              (!priv->snap_to_grid && item_y + item_height > avail_height))
             {
               item_x += g_array_index (priv->line_natural,
                                        gfloat,
@@ -668,27 +702,40 @@ clutter_flow_layout_allocate (ClutterLayoutManager   *manager,
               item_y = y_off;
             }
 
-          new_y = y_off + ((line_item_count + 1) * (avail_height + priv->row_spacing))
-                / items_per_line;
-          item_height = new_y - item_y - priv->row_spacing;
+          if (priv->snap_to_grid)
+            {
+              new_y = y_off + ((line_item_count + 1) * (avail_height + priv->row_spacing))
+                    / items_per_line;
+              item_height = new_y - item_y - priv->row_spacing;
+            }
+          else
+            {
+              new_y = item_y + item_height + priv->row_spacing;
+            }
+
           item_width = g_array_index (priv->line_natural,
                                       gfloat,
                                       line_index);
+        }
 
-          if (!priv->is_homogeneous)
-            {
-              gfloat child_min, child_natural;
-
-              clutter_actor_get_preferred_width (child, item_height,
-                                                 &child_min,
-                                                 &child_natural);
-              item_width = MIN (item_width, child_natural);
+      if (!priv->is_homogeneous &&
+          !clutter_actor_needs_expand (child,
+                                       CLUTTER_ORIENTATION_HORIZONTAL))
+        {
+          clutter_actor_get_preferred_width (child, item_height,
+                                             &child_min,
+                                             &child_natural);
+          item_width = MIN (item_width, child_natural);
+        }
 
-              clutter_actor_get_preferred_height (child, item_width,
-                                                  &child_min,
-                                                  &child_natural);
-              item_height = MIN (item_height, child_natural);
-            }
+      if (!priv->is_homogeneous &&
+          !clutter_actor_needs_expand (child,
+                                       CLUTTER_ORIENTATION_VERTICAL))
+        {
+          clutter_actor_get_preferred_height (child, item_width,
+                                              &child_min,
+                                              &child_natural);
+          item_height = MIN (item_height, child_natural);
         }
 
       CLUTTER_NOTE (LAYOUT,
@@ -789,6 +836,11 @@ clutter_flow_layout_set_property (GObject      *gobject,
                                           g_value_get_float (value));
       break;
 
+    case PROP_SNAP_TO_GRID:
+      clutter_flow_layout_set_snap_to_grid (self,
+                                            g_value_get_boolean (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
       break;
@@ -837,6 +889,10 @@ clutter_flow_layout_get_property (GObject    *gobject,
       g_value_set_float (value, priv->max_row_height);
       break;
 
+    case PROP_SNAP_TO_GRID:
+      g_value_set_boolean (value, priv->snap_to_grid);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
       break;
@@ -1004,6 +1060,21 @@ clutter_flow_layout_class_init (ClutterFlowLayoutClass *klass)
                         -1.0,
                         CLUTTER_PARAM_READWRITE);
 
+  /**
+   * ClutterFlowLayout:snap-to-grid:
+   *
+   * Whether the #ClutterFlowLayout should arrange its children
+   * on a grid
+   *
+   * Since: 1.16
+   */
+  flow_properties[PROP_SNAP_TO_GRID] =
+    g_param_spec_boolean ("snap-to-grid",
+                          P_("Snap to grid"),
+                          P_("Snap to grid"),
+                          TRUE,
+                          CLUTTER_PARAM_READWRITE);
+
   gobject_class->finalize = clutter_flow_layout_finalize;
   gobject_class->set_property = clutter_flow_layout_set_property;
   gobject_class->get_property = clutter_flow_layout_get_property;
@@ -1029,6 +1100,7 @@ clutter_flow_layout_init (ClutterFlowLayout *self)
 
   priv->line_min = NULL;
   priv->line_natural = NULL;
+  priv->snap_to_grid = TRUE;
 }
 
 /**
@@ -1434,3 +1506,51 @@ clutter_flow_layout_get_row_height (ClutterFlowLayout *layout,
   if (max_height)
     *max_height = layout->priv->max_row_height;
 }
+
+/**
+ * clutter_flow_layout_set_snap_to_grid:
+ * @layout: a #ClutterFlowLayout
+ * @snap_to_grid: %TRUE if @layout should place its children on a grid
+ *
+ * Whether the @layout should place its children on a grid.
+ *
+ * Since: 1.16
+ */
+void
+clutter_flow_layout_set_snap_to_grid (ClutterFlowLayout *layout,
+                                      gboolean           snap_to_grid)
+{
+  ClutterFlowLayoutPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout));
+
+  priv = layout->priv;
+
+  if (priv->snap_to_grid != snap_to_grid)
+    {
+      priv->snap_to_grid = snap_to_grid;
+
+      clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout));
+
+      g_object_notify_by_pspec (G_OBJECT (layout),
+                                flow_properties[PROP_SNAP_TO_GRID]);
+    }
+}
+
+/**
+ * clutter_flow_layout_get_snap_to_grid:
+ * @layout: a #ClutterFlowLayout
+ *
+ * Retrieves the value of #ClutterFlowLayout:snap-to-grid property
+ *
+ * Return value: %TRUE if the @layout is placing its children on a grid
+ *
+ * Since: 1.16
+ */
+gboolean
+clutter_flow_layout_get_snap_to_grid (ClutterFlowLayout *layout)
+{
+  g_return_val_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout), FALSE);
+
+  return layout->priv->snap_to_grid;
+}
diff --git a/clutter/clutter-flow-layout.h b/clutter/clutter-flow-layout.h
index abbf82c..2acacdd 100644
--- a/clutter/clutter-flow-layout.h
+++ b/clutter/clutter-flow-layout.h
@@ -104,6 +104,11 @@ void                   clutter_flow_layout_set_row_height     (ClutterFlowLayout
 void                   clutter_flow_layout_get_row_height     (ClutterFlowLayout      *layout,
                                                                gfloat                 *min_height,
                                                                gfloat                 *max_height);
+CLUTTER_AVAILABLE_IN_1_16
+void                   clutter_flow_layout_set_snap_to_grid   (ClutterFlowLayout      *layout,
+                                                               gboolean                snap_to_grid);
+CLUTTER_AVAILABLE_IN_1_16
+gboolean               clutter_flow_layout_get_snap_to_grid   (ClutterFlowLayout      *layout);
 
 G_END_DECLS
 
diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols
index 7316538..9e53a3c 100644
--- a/clutter/clutter.symbols
+++ b/clutter/clutter.symbols
@@ -707,6 +707,7 @@ clutter_flow_layout_get_column_spacing
 clutter_flow_layout_get_column_width
 clutter_flow_layout_get_homogeneous
 clutter_flow_layout_get_orientation
+clutter_flow_layout_get_snap_to_grid
 clutter_flow_layout_get_row_height
 clutter_flow_layout_get_row_spacing
 clutter_flow_layout_get_type
@@ -715,6 +716,7 @@ clutter_flow_layout_set_column_spacing
 clutter_flow_layout_set_column_width
 clutter_flow_layout_set_homogeneous
 clutter_flow_layout_set_orientation
+clutter_flow_layout_set_snap_to_grid
 clutter_flow_layout_set_row_height
 clutter_flow_layout_set_row_spacing
 clutter_flow_orientation_get_type
diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt
index 1fd6837..9e910d1 100644
--- a/doc/reference/clutter/clutter-sections.txt
+++ b/doc/reference/clutter/clutter-sections.txt
@@ -2298,6 +2298,8 @@ clutter_flow_layout_set_homogeneous
 clutter_flow_layout_get_homogeneous
 clutter_flow_layout_set_orientation
 clutter_flow_layout_get_orientation
+clutter_flow_layout_set_snap_to_grid
+clutter_flow_layout_get_snap_to_grid
 
 <SUBSECTION>
 clutter_flow_layout_set_column_spacing
diff --git a/examples/flow-layout.c b/examples/flow-layout.c
index f21c3a4..f688884 100644
--- a/examples/flow-layout.c
+++ b/examples/flow-layout.c
@@ -9,6 +9,7 @@ static gboolean is_homogeneous = FALSE;
 static gboolean vertical       = FALSE;
 static gboolean random_size    = FALSE;
 static gboolean fixed_size     = FALSE;
+static gboolean snap_to_grid   = TRUE;
 
 static gint     n_rects        = N_RECTS;
 static gint     x_spacing      = 0;
@@ -64,6 +65,13 @@ static GOptionEntry entries[] = {
     &fixed_size,
     "Fix the layout size", NULL
   },
+  {
+    "no-snap-to-grid", 's',
+    G_OPTION_FLAG_REVERSE,
+    G_OPTION_ARG_NONE,
+    &snap_to_grid,
+    "Don't snap elements to grid", NULL
+  },
   { NULL }
 };
 
@@ -102,6 +110,8 @@ main (int argc, char *argv[])
                                           x_spacing);
   clutter_flow_layout_set_row_spacing (CLUTTER_FLOW_LAYOUT (layout),
                                        y_spacing);
+  clutter_flow_layout_set_snap_to_grid (CLUTTER_FLOW_LAYOUT (layout),
+                                        snap_to_grid);
 
   box = clutter_actor_new ();
   clutter_actor_set_layout_manager (box, layout);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]