]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkgrid.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkgrid.c
index f6ec2f11113f2450dc7b9c3ca6deb676790fba15..571f8266f2039408d600cfae7876dd4558c1811c 100644 (file)
@@ -13,9 +13,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -44,7 +42,8 @@
  *
  * Children are added using gtk_grid_attach(). They can span multiple
  * rows or columns. It is also possible to add a child next to an
- * existing child, using gtk_grid_attach_next_to().
+ * existing child, using gtk_grid_attach_next_to(). The behaviour of
+ * GtkGrid when several children occupy the same grid cell is undefined.
  *
  * GtkGrid can be used like a #GtkBox by just using gtk_container_add(),
  * which will place children next to each other in the direction determined
@@ -772,37 +771,72 @@ gtk_grid_request_spanning (GtkGridRequest *request,
       /* If we need to request more space for this child to fill
        * its requisition, then divide up the needed space amongst the
        * lines it spans, favoring expandable lines if any.
+       *
+       * When doing homogeneous allocation though, try to keep the
+       * line allocations even, since we're going to force them to
+       * be the same anyway, and we don't want to introduce unnecessary
+       * extra space.
        */
       if (span_minimum < minimum)
         {
-          extra = minimum - span_minimum;
-          expand = span_expand;
-          for (i = 0; i < attach->span; i++)
+          if (linedata->homogeneous)
             {
-              line = &lines->lines[attach->pos - lines->min + i];
-              if (force_expand || line->expand)
+              gint total, m;
+
+              total = minimum - (attach->span - 1) * linedata->spacing;
+              m = total / attach->span + (total % attach->span ? 1 : 0);
+              for (i = 0; i < attach->span; i++)
                 {
-                  line_extra = extra / expand;
-                  line->minimum += line_extra;
-                  extra -= line_extra;
-                  expand -= 1;
+                  line = &lines->lines[attach->pos - lines->min + i];
+                  line->minimum = MAX(line->minimum, m);
+                }
+            }
+          else
+            {
+              extra = minimum - span_minimum;
+              expand = span_expand;
+              for (i = 0; i < attach->span; i++)
+                {
+                  line = &lines->lines[attach->pos - lines->min + i];
+                  if (force_expand || line->expand)
+                    {
+                      line_extra = extra / expand;
+                      line->minimum += line_extra;
+                      extra -= line_extra;
+                      expand -= 1;
+                    }
                 }
             }
         }
 
       if (span_natural < natural)
         {
-          extra = natural - span_natural;
-          expand = span_expand;
-          for (i = 0; i < attach->span; i++)
+          if (linedata->homogeneous)
             {
-              line = &lines->lines[attach->pos - lines->min + i];
-              if (force_expand || line->expand)
+              gint total, n;
+
+              total = natural - (attach->span - 1) * linedata->spacing;
+              n = total / attach->span + (total % attach->span ? 1 : 0);
+              for (i = 0; i < attach->span; i++)
                 {
-                  line_extra = extra / expand;
-                  line->natural += line_extra;
-                  extra -= line_extra;
-                  expand -= 1;
+                  line = &lines->lines[attach->pos - lines->min + i];
+                  line->natural = MAX(line->natural, n);
+                }
+            }
+          else
+            {
+              extra = natural - span_natural;
+              expand = span_expand;
+              for (i = 0; i < attach->span; i++)
+                {
+                  line = &lines->lines[attach->pos - lines->min + i];
+                  if (force_expand || line->expand)
+                    {
+                      line_extra = extra / expand;
+                      line->natural += line_extra;
+                      extra -= line_extra;
+                      expand -= 1;
+                    }
                 }
             }
         }
@@ -927,8 +961,13 @@ gtk_grid_request_sum (GtkGridRequest *request,
   linedata = &priv->linedata[orientation];
   lines = &request->lines[orientation];
 
-  min = (nonempty - 1) * linedata->spacing;
-  nat = (nonempty - 1) * linedata->spacing;
+  min = 0;
+  nat = 0;
+  if (nonempty > 0)
+    {
+      min = (nonempty - 1) * linedata->spacing;
+      nat = (nonempty - 1) * linedata->spacing;
+    }
 
   for (i = 0; i < lines->max - lines->min; i++)
     {
@@ -982,6 +1021,9 @@ gtk_grid_request_allocate (GtkGridRequest *request,
 
   gtk_grid_request_compute_expand (request, orientation, &nonempty, &expand);
 
+  if (nonempty == 0)
+    return;
+
   linedata = &priv->linedata[orientation];
   lines = &request->lines[orientation];
 
@@ -1453,7 +1495,7 @@ gtk_grid_attach (GtkGrid   *grid,
  * gtk_grid_attach_next_to:
  * @grid: a #GtkGrid
  * @child: the widget to add
- * @sibling (allow-none): the child of @grid that @child will be placed
+ * @sibling: (allow-none): the child of @grid that @child will be placed
  *     next to, or %NULL to place @child at the beginning or end
  * @side: the side of @sibling that @child is positioned next to
  * @width: the number of columns that @child will span
@@ -1465,6 +1507,9 @@ gtk_grid_attach (GtkGrid   *grid,
  * @side. When @sibling is %NULL, the widget is placed in row (for
  * left or right placement) or column 0 (for top or bottom placement),
  * at the end indicated by @side.
+ *
+ * Attaching widgets labeled [1], [2], [3] with @sibling == %NULL and
+ * @side == %GTK_POS_LEFT yields a layout of [3][2][1].
  */
 void
 gtk_grid_attach_next_to (GtkGrid         *grid,
@@ -1515,20 +1560,22 @@ gtk_grid_attach_next_to (GtkGrid         *grid,
       switch (side)
         {
         case GTK_POS_LEFT:
-          left = find_attach_position (grid, GTK_ORIENTATION_HORIZONTAL, 0, height, TRUE);
+          left = find_attach_position (grid, GTK_ORIENTATION_HORIZONTAL, 0, height, FALSE);
+          left -= width;
           top = 0;
           break;
         case GTK_POS_RIGHT:
-          left = find_attach_position (grid, GTK_ORIENTATION_HORIZONTAL, 0, height, FALSE);
+          left = find_attach_position (grid, GTK_ORIENTATION_HORIZONTAL, 0, height, TRUE);
           top = 0;
           break;
         case GTK_POS_TOP:
           left = 0;
-          top = find_attach_position (grid, GTK_ORIENTATION_VERTICAL, 0, width, TRUE);
+          top = find_attach_position (grid, GTK_ORIENTATION_VERTICAL, 0, width, FALSE);
+          top -= height;
           break;
         case GTK_POS_BOTTOM:
           left = 0;
-          top = find_attach_position (grid, GTK_ORIENTATION_VERTICAL, 0, width, FALSE);
+          top = find_attach_position (grid, GTK_ORIENTATION_VERTICAL, 0, width, TRUE);
           break;
         default:
           g_assert_not_reached ();
@@ -1547,7 +1594,7 @@ gtk_grid_attach_next_to (GtkGrid         *grid,
  * Gets the child of @grid whose area covers the grid
  * cell whose upper left corner is at @left, @top.
  *
- * Returns: the child at the given position, or %NULL
+ * Returns: (transfer none): the child at the given position, or %NULL
  *
  * Since: 3.2
  */
@@ -1556,10 +1603,14 @@ gtk_grid_get_child_at (GtkGrid *grid,
                        gint     left,
                        gint     top)
 {
-  GtkGridPrivate *priv = grid->priv;
+  GtkGridPrivate *priv;
   GtkGridChild *child;
   GList *list;
 
+  g_return_val_if_fail (GTK_IS_GRID (grid), NULL);
+
+  priv = grid->priv;
+
   for (list = priv->children; list; list = list->next)
     {
       child = list->data;
@@ -1591,13 +1642,15 @@ void
 gtk_grid_insert_row (GtkGrid *grid,
                      gint     position)
 {
-  GtkGridPrivate *priv = grid->priv;
+  GtkGridPrivate *priv;
   GtkGridChild *child;
   GList *list;
   gint top, height;
 
   g_return_if_fail (GTK_IS_GRID (grid));
 
+  priv = grid->priv;
+
   for (list = priv->children; list; list = list->next)
     {
       child = list->data;
@@ -1635,13 +1688,15 @@ void
 gtk_grid_insert_column (GtkGrid *grid,
                         gint     position)
 {
-  GtkGridPrivate *priv = grid->priv;
+  GtkGridPrivate *priv;
   GtkGridChild *child;
   GList *list;
   gint left, width;
 
   g_return_if_fail (GTK_IS_GRID (grid));
 
+  priv = grid->priv;
+
   for (list = priv->children; list; list = list->next)
     {
       child = list->data;