[goocanvas] Fixed text alignment bug in tables.



commit 12268ad65f2d5b408492323026717beafebaec08
Author: Damon Chaplin <damon gnome org>
Date:   Wed Sep 14 10:07:45 2011 +0100

    Fixed text alignment bug in tables.
    
    2011-09-14  Damon Chaplin  <damon gnome org>
    
    	    * src/goocanvasitem.h: added get_requested_area_for_width() method.
    	    get_requested_height() didn't work for aligned text items as the
    	    position of the item moves horizontally due to the allocated width,
    	    and this wasn't being taken into account in the layout code.
    
    	    * src/goocanvastable.c (goo_canvas_table_update_requested_heights): use
    	    get_requested_area_for_width() if available.
    
    	    * src/goocanvastext.c (goo_canvas_text_get_requested_area_for_width):
    	    use this instead of get_requested_height() so aligned text should work.
    
    	    * demo/mv-demo-table.c:
    	    * demo/demo-table.c: added tests for the above.

 .gitignore                |    2 +
 ChangeLog                 |   16 ++++
 demo/demo-table.c         |  187 ++++++++++++++++++++++++++++++++++++--------
 demo/mv-demo-table.c      |  181 ++++++++++++++++++++++++++++++++++++--------
 src/goocanvasitem.c       |   34 ++++++++
 src/goocanvasitem.h       |   19 ++++-
 src/goocanvasitemsimple.c |    6 ++
 src/goocanvastable.c      |   42 +++++++++-
 src/goocanvastext.c       |   80 +++++++++++++------
 9 files changed, 469 insertions(+), 98 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 7096234..592f385 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
 *.loT
 *.la
 *.gmo
+*.orig
+*.rej
 *~
 
 Makefile
diff --git a/ChangeLog b/ChangeLog
index 6dbc360..2d88c06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2011-09-14  Damon Chaplin  <damon gnome org>
+
+	* src/goocanvasitem.h: added get_requested_area_for_width() method.
+	get_requested_height() didn't work for aligned text items as the
+	position of the item moves horizontally due to the allocated width,
+	and this wasn't being taken into account in the layout code.
+
+	* src/goocanvastable.c (goo_canvas_table_update_requested_heights): use
+	get_requested_area_for_width() if available.
+
+	* src/goocanvastext.c (goo_canvas_text_get_requested_area_for_width): 
+	use this instead of get_requested_height() so aligned text should work.
+
+	* demo/mv-demo-table.c: 
+	* demo/demo-table.c: added tests for the above.
+
 2011-08-17  Damon Chaplin  <damon gnome org>
 
 	* src/goocanvastext.c (goo_canvas_text_get_requested_height): when
diff --git a/demo/demo-table.c b/demo/demo-table.c
index 35ede48..94bd244 100644
--- a/demo/demo-table.c
+++ b/demo/demo-table.c
@@ -5,7 +5,9 @@
 
 #define DEMO_RECT_ITEM 0
 #define DEMO_TEXT_ITEM 1
-#define DEMO_WIDGET_ITEM 2
+#define DEMO_TEXT_ITEM_2 2
+#define DEMO_TEXT_ITEM_3 3
+#define DEMO_WIDGET_ITEM 4
 
 
 static gboolean
@@ -31,7 +33,11 @@ create_demo_item (GooCanvasItem *table,
 		  gint           column,
 		  gint           rows,
 		  gint           columns,
-		  gchar         *text)
+		  gchar         *text,
+		  gdouble	 width,
+		  gdouble        xalign,
+		  gdouble	 yalign,
+		  PangoAlignment text_alignment)
 {
   GooCanvasItem *item = NULL;
   GtkWidget *widget;
@@ -46,7 +52,11 @@ create_demo_item (GooCanvasItem *table,
 				  NULL);
       break;
     case DEMO_TEXT_ITEM:
-      item = goo_canvas_text_new (table, text, 0, 0, -1, GOO_CANVAS_ANCHOR_NW, NULL);
+    case DEMO_TEXT_ITEM_2:
+    case DEMO_TEXT_ITEM_3:
+      item = goo_canvas_text_new (table, text, 0, 0, width, GOO_CANVAS_ANCHOR_NW,
+				  "alignment",  text_alignment,
+				  NULL);
       break;
     case DEMO_WIDGET_ITEM:
       widget = gtk_button_new_with_label (text);
@@ -64,17 +74,23 @@ create_demo_item (GooCanvasItem *table,
   g_value_set_uint (&value, columns);
   goo_canvas_item_set_child_property (table, item, "columns", &value);
 
+  goo_canvas_item_set_child_properties (table, item,
+					"x-expand", TRUE,
+					"y-expand", TRUE,
+					"x-align", xalign,
+					"y-align", yalign,
+					NULL);
+
   /* Test the get function. */
   goo_canvas_item_get_child_property (table, item, "row", &value);
   new_row = g_value_get_uint (&value);
   if (new_row != row)
     g_warning ("Got bad row setting: %i should be: %i\n", new_row, row);
 
-#if 1
+  /* If we make the item's fill the cells then alignment can't be used. */
+#if 0
   goo_canvas_item_set_child_properties (table, item,
-					"x-expand", TRUE,
 					"x-fill", TRUE,
-					"y-expand", TRUE,
 					"y-fill", TRUE,
 					NULL);
 #endif
@@ -94,7 +110,8 @@ create_table (GooCanvasItem *parent,
 	      gdouble        y,
 	      gdouble        rotation,
 	      gdouble        scale,
-	      gint           demo_item_type)
+	      gint           demo_item_type,
+	      gboolean       show_grid_lines)
 {
   GooCanvasItem *table;
 
@@ -103,6 +120,13 @@ create_table (GooCanvasItem *parent,
 				"row-spacing", 4.0,
 				"column-spacing", 4.0,
 				NULL);
+
+  if (show_grid_lines)
+    g_object_set (table,
+		  "horz-grid-line-width", 1.0f,
+		  "vert-grid-line-width", 1.0f,
+		  NULL);
+
   goo_canvas_item_translate (table, x, y);
 #if 1
   goo_canvas_item_rotate (table, rotation, 0, 0);
@@ -128,27 +152,110 @@ create_table (GooCanvasItem *parent,
   if (embedding_level)
     {
       gint level = embedding_level - 1;
-      create_table (table, 0, 0, level, 50, 50, 0, 0.7, demo_item_type);
-      create_table (table, 0, 1, level, 50, 50, 45, 1.0, demo_item_type);
-      create_table (table, 0, 2, level, 50, 50, 90, 1.0, demo_item_type);
-      create_table (table, 1, 0, level, 50, 50, 135, 1.0, demo_item_type);
-      create_table (table, 1, 1, level, 50, 50, 180, 1.5, demo_item_type);
-      create_table (table, 1, 2, level, 50, 50, 225, 1.0, demo_item_type);
-      create_table (table, 2, 0, level, 50, 50, 270, 1.0, demo_item_type);
-      create_table (table, 2, 1, level, 50, 50, 315, 1.0, demo_item_type);
-      create_table (table, 2, 2, level, 50, 50, 360, 2.0, demo_item_type);
+      create_table (table, 0, 0, level, 50, 50, 0, 0.7, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 0, 1, level, 50, 50, 45, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 0, 2, level, 50, 50, 90, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 1, 0, level, 50, 50, 135, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 1, 1, level, 50, 50, 180, 1.5, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 1, 2, level, 50, 50, 225, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 2, 0, level, 50, 50, 270, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 2, 1, level, 50, 50, 315, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 2, 2, level, 50, 50, 360, 2.0, demo_item_type,
+		    show_grid_lines);
+    }
+  else if (demo_item_type == DEMO_TEXT_ITEM_2)
+    {
+      create_demo_item (table, demo_item_type, 0, 0, 1, 1,
+			"(0.0,0.0)\nleft\naligned",
+			-1, 0, 0, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 1, 1, 1,
+			"(0.5,0.0)\ncenter\naligned",
+			-1, 0.5, 0, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 0, 2, 1, 1,
+			"(1.0,0.0)\nright\naligned",
+			-1, 1, 0, PANGO_ALIGN_RIGHT);
+
+      /* The layout width shouldn't really make any difference in this test. */
+      create_demo_item (table, demo_item_type, 1, 0, 1, 1,
+			"(0.5,0.5)\ncenter\naligned",
+			50, 0.5, 0.5, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 1, 1, 1, 1,
+			"(0.0,1.0)\nright\naligned",
+			100, 0, 1.0, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 1, 2, 1, 1,
+			"(0.0,0.5)\nleft\naligned",
+			200, 0, 0.5, PANGO_ALIGN_LEFT);
+
+      create_demo_item (table, demo_item_type, 2, 0, 1, 1,
+			"(1.0,1.0)\ncenter\naligned",
+			-1, 1, 1, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 2, 1, 1, 1,
+			"(1,0.5)\nright\naligned",
+			-1, 1.0, 0.5, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 2, 2, 1, 1,
+			"(0.0,0.0)\nleft\naligned",
+			-1, 0, 0, PANGO_ALIGN_LEFT);
+    }
+  else if (demo_item_type == DEMO_TEXT_ITEM_3)
+    {
+      create_demo_item (table, demo_item_type, 0, 0, 1, 1,
+			"width 50 align 0.0, 0.0 text left aligned",
+			50, 0, 0, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 1, 1, 1,
+			"width 100 align 0.5, 0.0 text center aligned",
+			100, 0.5, 0, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 0, 2, 1, 1,
+			"width 150 align 1.0, 0.0 text right aligned",
+			150, 1, 0, PANGO_ALIGN_RIGHT);
+
+      create_demo_item (table, demo_item_type, 1, 0, 1, 1,
+			"width 50 align 0.5, 0.5 text center aligned",
+			50, 0.5, 0.5, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 1, 1, 1, 1,
+			"width 100 align 0.0, 1.0 text right aligned",
+			100, 0, 1.0, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 1, 2, 1, 1,
+			"width 200 align 0.0, 0.5 text left aligned",
+			200, 0, 0.5, PANGO_ALIGN_LEFT);
+
+      create_demo_item (table, demo_item_type, 2, 0, 1, 1,
+			"width 50 align 1.0, 1.0 text center aligned",
+			50, 1, 1, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 2, 1, 1, 1,
+			"width 100 align 1, 0.5 text right aligned",
+			100, 1.0, 0.5, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 2, 2, 1, 1,
+			"width 50 align 0.0, 0.0 text left aligned",
+			50, 0, 0, PANGO_ALIGN_LEFT);
     }
   else
     {
-      create_demo_item (table, demo_item_type, 0, 0, 1, 1, "(0,0)");
-      create_demo_item (table, demo_item_type, 0, 1, 1, 1, "(1,0)");
-      create_demo_item (table, demo_item_type, 0, 2, 1, 1, "(2,0)");
-      create_demo_item (table, demo_item_type, 1, 0, 1, 1, "(0,1)");
-      create_demo_item (table, demo_item_type, 1, 1, 1, 1, "(1,1)");
-      create_demo_item (table, demo_item_type, 1, 2, 1, 1, "(2,1)");
-      create_demo_item (table, demo_item_type, 2, 0, 1, 1, "(0,2)");
-      create_demo_item (table, demo_item_type, 2, 1, 1, 1, "(1,2)");
-      create_demo_item (table, demo_item_type, 2, 2, 1, 1, "(2,2)");
+      create_demo_item (table, demo_item_type, 0, 0, 1, 1, "(0,0)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 1, 1, 1, "(1,0)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 2, 1, 1, "(2,0)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 1, 0, 1, 1, "(0,1)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 1, 1, 1, 1, "(1,1)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 1, 2, 1, 1, "(2,1)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 2, 0, 1, 1, "(0,2)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 2, 1, 1, 1, "(1,2)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 2, 2, 1, 1, "(2,2)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
     }
 
   return table;
@@ -285,7 +392,7 @@ create_table_page (void)
 
   canvas = goo_canvas_new ();
   gtk_widget_set_size_request (canvas, 600, 450);
-  goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 2000);
+  goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 3000);
   gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);
 
   root = goo_canvas_get_root_item (GOO_CANVAS (canvas));
@@ -296,28 +403,40 @@ create_table_page (void)
 #endif
 
 #if 1
-  create_table (root, -1, -1, 0, 10, 10, 0, 1.0, DEMO_TEXT_ITEM);
-  create_table (root, -1, -1, 0, 180, 10, 30, 1.0, DEMO_TEXT_ITEM);
-  create_table (root, -1, -1, 0, 350, 10, 60, 1.0, DEMO_TEXT_ITEM);
-  create_table (root, -1, -1, 0, 500, 10, 90, 1.0, DEMO_TEXT_ITEM);
+  create_table (root, -1, -1, 0, 10, 10, 0, 1.0, DEMO_TEXT_ITEM, FALSE);
+  create_table (root, -1, -1, 0, 180, 10, 30, 1.0, DEMO_TEXT_ITEM, FALSE);
+  create_table (root, -1, -1, 0, 350, 10, 60, 1.0, DEMO_TEXT_ITEM, FALSE);
+  create_table (root, -1, -1, 0, 500, 10, 90, 1.0, DEMO_TEXT_ITEM, FALSE);
 #endif
 
 #if 1
-  table = create_table (root, -1, -1, 0, 30, 150, 0, 1.0, DEMO_TEXT_ITEM);
+  table = create_table (root, -1, -1, 0, 30, 150, 0, 1.0, DEMO_TEXT_ITEM, FALSE);
   g_object_set (table, "width", 300.0, "height", 100.0, NULL);
 #endif
 
 #if 1
-  create_table (root, -1, -1, 1, 200, 200, 30, 0.8, DEMO_TEXT_ITEM);
+  table = create_table (root, -1, -1, 0, 30, 1400, 0, 1.0, DEMO_TEXT_ITEM_2, TRUE);
+  g_object_set (table, "width", 300.0, "height", 300.0, NULL);
+
+  table = create_table (root, -1, -1, 0, 630, 1430, 30, 1.0, DEMO_TEXT_ITEM_2, TRUE);
+  g_object_set (table, "width", 300.0, "height", 300.0, NULL);
+
+
+  table = create_table (root, -1, -1, 0, 30, 1800, 0, 1.0, DEMO_TEXT_ITEM_3, TRUE);
+  table = create_table (root, -1, -1, 0, 630, 1830, 30, 1.0, DEMO_TEXT_ITEM_3, TRUE);
+#endif
+
+#if 1
+  create_table (root, -1, -1, 1, 200, 200, 30, 0.8, DEMO_TEXT_ITEM, FALSE);
 #endif
 
 #if 1
-  table = create_table (root, -1, -1, 0, 10, 700, 0, 1.0, DEMO_WIDGET_ITEM);
+  table = create_table (root, -1, -1, 0, 10, 700, 0, 1.0, DEMO_WIDGET_ITEM, FALSE);
   g_object_set (table, "width", 300.0, "height", 200.0, NULL);
 #endif
 
-  create_width_for_height_table (root, 100, 1000, 200, -1, 0);
 #if 1
+  create_width_for_height_table (root, 100, 1000, 200, -1, 0);
   create_width_for_height_table (root, 100, 1200, 300, -1, 0);
 
   create_width_for_height_table (root, 500, 1000, 200, -1, 30);
diff --git a/demo/mv-demo-table.c b/demo/mv-demo-table.c
index 9ad4d08..ff9542a 100644
--- a/demo/mv-demo-table.c
+++ b/demo/mv-demo-table.c
@@ -5,6 +5,8 @@
 
 #define DEMO_RECT_ITEM 0
 #define DEMO_TEXT_ITEM 1
+#define DEMO_TEXT_ITEM_2 2
+#define DEMO_TEXT_ITEM_3 3
 
 static GooCanvas *canvas;
 
@@ -31,7 +33,11 @@ create_demo_item (GooCanvasItemModel *table,
 		  gint           column,
 		  gint           rows,
 		  gint           columns,
-		  gchar         *text)
+		  gchar         *text,
+		  gdouble	 width,
+		  gdouble        xalign,
+		  gdouble	 yalign,
+		  PangoAlignment text_alignment)
 {
   GooCanvasItemModel *model = NULL;
   GooCanvasItem *item;
@@ -46,7 +52,10 @@ create_demo_item (GooCanvasItemModel *table,
 					 NULL);
       break;
     case DEMO_TEXT_ITEM:
-      model = goo_canvas_text_model_new (table, text, 0, 0, -1, GOO_CANVAS_ANCHOR_NW,
+    case DEMO_TEXT_ITEM_2:
+    case DEMO_TEXT_ITEM_3:
+      model = goo_canvas_text_model_new (table, text, 0, 0, width, GOO_CANVAS_ANCHOR_NW,
+					 "alignment",  text_alignment,
 					 NULL);
       break;
     }
@@ -61,17 +70,23 @@ create_demo_item (GooCanvasItemModel *table,
   g_value_set_uint (&value, columns);
   goo_canvas_item_model_set_child_property (table, model, "columns", &value);
 
+  goo_canvas_item_model_set_child_properties (table, model,
+					      "x-expand", TRUE,
+					      "y-expand", TRUE,
+					      "x-align", xalign,
+					      "y-align", yalign,
+					      NULL);
+
   /* Test the get function. */
   goo_canvas_item_model_get_child_property (table, model, "row", &value);
   new_row = g_value_get_uint (&value);
   if (new_row != row)
     g_warning ("Got bad row setting: %i should be: %i\n", new_row, row);
 
-#if 1
+  /* If we make the item's fill the cells then alignment can't be used. */
+#if 0
   goo_canvas_item_model_set_child_properties (table, model,
-					      "x-expand", TRUE,
 					      "x-fill", TRUE,
-					      "y-expand", TRUE,
 					      "y-fill", TRUE,
 					      NULL);
 #endif
@@ -92,7 +107,8 @@ create_table (GooCanvasItemModel *parent,
 	      gdouble        y,
 	      gdouble        rotation,
 	      gdouble        scale,
-	      gint           demo_item_type)
+	      gint           demo_item_type,
+	      gboolean       show_grid_lines)
 {
   GooCanvasItemModel *table;
 
@@ -101,6 +117,13 @@ create_table (GooCanvasItemModel *parent,
 				      "row-spacing", 4.0,
 				      "column-spacing", 4.0,
 				      NULL);
+
+  if (show_grid_lines)
+    g_object_set (table,
+		  "horz-grid-line-width", 1.0f,
+		  "vert-grid-line-width", 1.0f,
+		  NULL);
+
   goo_canvas_item_model_translate (table, x, y);
 #if 1
   goo_canvas_item_model_rotate (table, rotation, 0, 0);
@@ -126,27 +149,110 @@ create_table (GooCanvasItemModel *parent,
   if (embedding_level)
     {
       gint level = embedding_level - 1;
-      create_table (table, 0, 0, level, 50, 50, 0, 0.7, demo_item_type);
-      create_table (table, 0, 1, level, 50, 50, 45, 1.0, demo_item_type);
-      create_table (table, 0, 2, level, 50, 50, 90, 1.0, demo_item_type);
-      create_table (table, 1, 0, level, 50, 50, 135, 1.0, demo_item_type);
-      create_table (table, 1, 1, level, 50, 50, 180, 1.5, demo_item_type);
-      create_table (table, 1, 2, level, 50, 50, 225, 1.0, demo_item_type);
-      create_table (table, 2, 0, level, 50, 50, 270, 1.0, demo_item_type);
-      create_table (table, 2, 1, level, 50, 50, 315, 1.0, demo_item_type);
-      create_table (table, 2, 2, level, 50, 50, 360, 2.0, demo_item_type);
+      create_table (table, 0, 0, level, 50, 50, 0, 0.7, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 0, 1, level, 50, 50, 45, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 0, 2, level, 50, 50, 90, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 1, 0, level, 50, 50, 135, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 1, 1, level, 50, 50, 180, 1.5, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 1, 2, level, 50, 50, 225, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 2, 0, level, 50, 50, 270, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 2, 1, level, 50, 50, 315, 1.0, demo_item_type,
+		    show_grid_lines);
+      create_table (table, 2, 2, level, 50, 50, 360, 2.0, demo_item_type,
+		    show_grid_lines);
+    }
+  else if (demo_item_type == DEMO_TEXT_ITEM_2)
+    {
+      create_demo_item (table, demo_item_type, 0, 0, 1, 1,
+			"(0.0,0.0)\nleft\naligned",
+			-1, 0, 0, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 1, 1, 1,
+			"(0.5,0.0)\ncenter\naligned",
+			-1, 0.5, 0, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 0, 2, 1, 1,
+			"(1.0,0.0)\nright\naligned",
+			-1, 1, 0, PANGO_ALIGN_RIGHT);
+
+      /* The layout width shouldn't really make any difference in this test. */
+      create_demo_item (table, demo_item_type, 1, 0, 1, 1,
+			"(0.5,0.5)\ncenter\naligned",
+			50, 0.5, 0.5, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 1, 1, 1, 1,
+			"(0.0,1.0)\nright\naligned",
+			100, 0, 1.0, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 1, 2, 1, 1,
+			"(0.0,0.5)\nleft\naligned",
+			200, 0, 0.5, PANGO_ALIGN_LEFT);
+
+      create_demo_item (table, demo_item_type, 2, 0, 1, 1,
+			"(1.0,1.0)\ncenter\naligned",
+			-1, 1, 1, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 2, 1, 1, 1,
+			"(1,0.5)\nright\naligned",
+			-1, 1.0, 0.5, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 2, 2, 1, 1,
+			"(0.0,0.0)\nleft\naligned",
+			-1, 0, 0, PANGO_ALIGN_LEFT);
+    }
+  else if (demo_item_type == DEMO_TEXT_ITEM_3)
+    {
+      create_demo_item (table, demo_item_type, 0, 0, 1, 1,
+			"width 50 align 0.0, 0.0 text left aligned",
+			50, 0, 0, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 1, 1, 1,
+			"width 100 align 0.5, 0.0 text center aligned",
+			100, 0.5, 0, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 0, 2, 1, 1,
+			"width 150 align 1.0, 0.0 text right aligned",
+			150, 1, 0, PANGO_ALIGN_RIGHT);
+
+      create_demo_item (table, demo_item_type, 1, 0, 1, 1,
+			"width 50 align 0.5, 0.5 text center aligned",
+			50, 0.5, 0.5, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 1, 1, 1, 1,
+			"width 100 align 0.0, 1.0 text right aligned",
+			100, 0, 1.0, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 1, 2, 1, 1,
+			"width 200 align 0.0, 0.5 text left aligned",
+			200, 0, 0.5, PANGO_ALIGN_LEFT);
+
+      create_demo_item (table, demo_item_type, 2, 0, 1, 1,
+			"width 50 align 1.0, 1.0 text center aligned",
+			50, 1, 1, PANGO_ALIGN_CENTER);
+      create_demo_item (table, demo_item_type, 2, 1, 1, 1,
+			"width 100 align 1, 0.5 text right aligned",
+			100, 1.0, 0.5, PANGO_ALIGN_RIGHT);
+      create_demo_item (table, demo_item_type, 2, 2, 1, 1,
+			"width 50 align 0.0, 0.0 text left aligned",
+			50, 0, 0, PANGO_ALIGN_LEFT);
     }
   else
     {
-      create_demo_item (table, demo_item_type, 0, 0, 1, 1, "(0,0)");
-      create_demo_item (table, demo_item_type, 0, 1, 1, 1, "(1,0)");
-      create_demo_item (table, demo_item_type, 0, 2, 1, 1, "(2,0)");
-      create_demo_item (table, demo_item_type, 1, 0, 1, 1, "(0,1)");
-      create_demo_item (table, demo_item_type, 1, 1, 1, 1, "(1,1)");
-      create_demo_item (table, demo_item_type, 1, 2, 1, 1, "(2,1)");
-      create_demo_item (table, demo_item_type, 2, 0, 1, 1, "(0,2)");
-      create_demo_item (table, demo_item_type, 2, 1, 1, 1, "(1,2)");
-      create_demo_item (table, demo_item_type, 2, 2, 1, 1, "(2,2)");
+      create_demo_item (table, demo_item_type, 0, 0, 1, 1, "(0,0)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 1, 1, 1, "(1,0)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 0, 2, 1, 1, "(2,0)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 1, 0, 1, 1, "(0,1)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 1, 1, 1, 1, "(1,1)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 1, 2, 1, 1, "(2,1)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 2, 0, 1, 1, "(0,2)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 2, 1, 1, 1, "(1,2)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
+      create_demo_item (table, demo_item_type, 2, 2, 1, 1, "(2,2)",
+			-1, 0, 0.5, PANGO_ALIGN_LEFT);
     }
 
   return table;
@@ -289,7 +395,7 @@ create_table_page (void)
 
   canvas = (GooCanvas*) goo_canvas_new ();
   gtk_widget_set_size_request ((GtkWidget*) canvas, 600, 450);
-  goo_canvas_set_bounds (canvas, 0, 0, 1000, 2000);
+  goo_canvas_set_bounds (canvas, 0, 0, 1000, 3000);
   gtk_container_add (GTK_CONTAINER (scrolled_win), (GtkWidget*) canvas);
 
   root = goo_canvas_group_model_new (NULL, NULL);
@@ -302,23 +408,34 @@ create_table_page (void)
 #endif
 
 #if 1
-  create_table (root, -1, -1, 0, 10, 10, 0, 1.0, DEMO_TEXT_ITEM);
-  create_table (root, -1, -1, 0, 180, 10, 30, 1.0, DEMO_TEXT_ITEM);
-  create_table (root, -1, -1, 0, 350, 10, 60, 1.0, DEMO_TEXT_ITEM);
-  create_table (root, -1, -1, 0, 500, 10, 90, 1.0, DEMO_TEXT_ITEM);
+  create_table (root, -1, -1, 0, 10, 10, 0, 1.0, DEMO_TEXT_ITEM, FALSE);
+  create_table (root, -1, -1, 0, 180, 10, 30, 1.0, DEMO_TEXT_ITEM, FALSE);
+  create_table (root, -1, -1, 0, 350, 10, 60, 1.0, DEMO_TEXT_ITEM, FALSE);
+  create_table (root, -1, -1, 0, 500, 10, 90, 1.0, DEMO_TEXT_ITEM, FALSE);
 #endif
 
 #if 1
-  table = create_table (root, -1, -1, 0, 30, 150, 0, 1.0, DEMO_TEXT_ITEM);
+  table = create_table (root, -1, -1, 0, 30, 150, 0, 1.0, DEMO_TEXT_ITEM, FALSE);
   g_object_set (table, "width", 300.0, "height", 100.0, NULL);
 #endif
 
 #if 1
-  create_table (root, -1, -1, 1, 200, 200, 30, 0.8, DEMO_TEXT_ITEM);
+  table = create_table (root, -1, -1, 0, 30, 1400, 0, 1.0, DEMO_TEXT_ITEM_2, TRUE);
+  g_object_set (table, "width", 300.0, "height", 300.0, NULL);
+
+  table = create_table (root, -1, -1, 0, 630, 1430, 30, 1.0, DEMO_TEXT_ITEM_2, TRUE);
+  g_object_set (table, "width", 300.0, "height", 300.0, NULL);
+
+  table = create_table (root, -1, -1, 0, 30, 1800, 0, 1.0, DEMO_TEXT_ITEM_3, TRUE);
+  table = create_table (root, -1, -1, 0, 630, 1830, 30, 1.0, DEMO_TEXT_ITEM_3, TRUE);
+#endif
+
+#if 1
+  create_table (root, -1, -1, 1, 200, 200, 30, 0.8, DEMO_TEXT_ITEM, FALSE);
 #endif
 
 #if 0
-  table = create_table (root, -1, -1, 0, 10, 700, 0, 1.0, DEMO_WIDGET_ITEM);
+  table = create_table (root, -1, -1, 0, 10, 700, 0, 1.0, DEMO_WIDGET_ITEM, FALSE);
   g_object_set (table, "width", 300.0, "height", 200.0, NULL);
 #endif
 
diff --git a/src/goocanvasitem.c b/src/goocanvasitem.c
index 205f7b4..4010b4d 100644
--- a/src/goocanvasitem.c
+++ b/src/goocanvasitem.c
@@ -1753,6 +1753,40 @@ goo_canvas_item_get_requested_area (GooCanvasItem    *item,
 
 
 /**
+ * goo_canvas_item_get_requested_area_for_width:
+ * @item: a #GooCanvasItem.
+ * @cr: a cairo context.
+ * @width: the allocated width.
+ * @requested_area: a #GooCanvasBounds to return the requested area in, in the
+ *  parent's coordinate space. If %FALSE is returned, this is undefined.
+ * 
+ * This function is only intended to be used when implementing new canvas
+ * items, specifically layout items such as #GooCanvasTable.
+ *
+ * It gets the requested area of a child item, assuming it is allocated the
+ * given width. This is useful for text items whose requested height may change
+ * depending on the allocated width.
+ * 
+ * Returns: %TRUE if the item's requested area changes due to the new allocated
+ * width.
+ **/
+gboolean
+goo_canvas_item_get_requested_area_for_width (GooCanvasItem	*item,
+					      cairo_t          *cr,
+					      gdouble           width,
+					      GooCanvasBounds  *requested_area)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+
+  if (iface->get_requested_area_for_width)
+    return iface->get_requested_area_for_width (item, cr, width, requested_area);
+  else
+    return FALSE;
+}
+
+
+
+/**
  * goo_canvas_item_get_requested_height:
  * @item: a #GooCanvasItem.
  * @cr: a cairo context.
diff --git a/src/goocanvasitem.h b/src/goocanvasitem.h
index 76c61ec..d86c3bc 100644
--- a/src/goocanvasitem.h
+++ b/src/goocanvasitem.h
@@ -100,6 +100,13 @@ typedef struct _GooCanvasItem       GooCanvasItem;
  * @get_requested_area: returns the requested area of the item, in its parent's
  *  coordinate space. This is only used for items in layout containers such as
  *  #GooCanvasTable.
+ * @get_requested_height: returns the requested height of the item,
+ *  given a particular allocated width, using the parent's coordinate space.
+ *  Note that this method should only be used if the position of the item
+ *  remains unchanged. If the position might change use
+ *  get_requested_area_for_width() instead.
+ * @get_requested_area_for_width: returns the requested bounds of the item,
+ *  given a particular allocated width, using the parent's coordinate space.
  * @allocate_area: allocates the item's area, in its parent's coordinate space.
  *  The item must recalculate its bounds and request redraws of parts of the
  *  canvas if necessary. This is only used for items in layout containers such
@@ -111,8 +118,6 @@ typedef struct _GooCanvasItem       GooCanvasItem;
  * @is_visible: returns %TRUE if the item is currently visible.
  * @get_is_static: returns %TRUE if the item is static.
  * @set_is_static: notifies the item whether it is static or not.
- * @get_requested_height: returns the requested height of the item,
- *  given a particular allocated width, using the parent's coordinate space.
  * @get_model: gets the model that the canvas item is viewing.
  * @set_model: sets the model that the canvas item will view.
  * @enter_notify_event: signal emitted when the mouse enters the item.
@@ -292,13 +297,17 @@ struct _GooCanvasItemIface
 							 GooCanvasItem		*target,
 							 GdkEventScroll		*event);
 
+  gboolean              (* get_requested_area_for_width)(GooCanvasItem		*item,
+							 cairo_t		*cr,
+							 gdouble		 width,
+							 GooCanvasBounds	*requested_area);
+
   /*< private >*/
 
   /* Padding for future expansion */
   void (*_goo_canvas_reserved1) (void);
   void (*_goo_canvas_reserved2) (void);
   void (*_goo_canvas_reserved3) (void);
-  void (*_goo_canvas_reserved4) (void);
 };
 
 
@@ -445,6 +454,10 @@ void               goo_canvas_item_paint          (GooCanvasItem         *item,
 gboolean	   goo_canvas_item_get_requested_area (GooCanvasItem	*item,
 						       cairo_t          *cr,
 						       GooCanvasBounds  *requested_area);
+gboolean	   goo_canvas_item_get_requested_area_for_width (GooCanvasItem	*item,
+								 cairo_t          *cr,
+								 gdouble           width,
+								 GooCanvasBounds  *requested_area);
 gdouble            goo_canvas_item_get_requested_height (GooCanvasItem  *item,
 							 cairo_t	*cr,
 							 gdouble         width);
diff --git a/src/goocanvasitemsimple.c b/src/goocanvasitemsimple.c
index 8d3f001..e5e8941 100644
--- a/src/goocanvasitemsimple.c
+++ b/src/goocanvasitemsimple.c
@@ -1333,6 +1333,12 @@ goo_canvas_item_simple_allocate_area      (GooCanvasItem         *item,
   simple->bounds.x2 += x_offset;
   simple->bounds.y2 += y_offset;
 
+#if 0
+  g_print ("Offsets: %g, %g Allocated bounds: %g,%g - %g,%g\n",
+	   x_offset, y_offset, simple->bounds.x1,
+	   simple->bounds.y1, simple->bounds.x2, simple->bounds.y2);
+#endif
+
   /* Request a redraw of the new bounds. */
   goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 }
diff --git a/src/goocanvastable.c b/src/goocanvastable.c
index 66c18ee..1fe086e 100644
--- a/src/goocanvastable.c
+++ b/src/goocanvastable.c
@@ -1877,6 +1877,8 @@ goo_canvas_table_update_requested_heights (GooCanvasItem       *item,
   GooCanvasTableChildLayoutData *child_data;
   gint start_column, end_column, i, row, end;
   gdouble x, max_width, width, requested_width, requested_height, height = 0.0;
+  GooCanvasItemIface *iface;
+  GooCanvasBounds bounds;
 
   /* Just return if we've already calculated requested heights for this exact
      width. */
@@ -1912,10 +1914,42 @@ goo_canvas_table_update_requested_heights (GooCanvasItem       *item,
       if (!(child->flags[HORZ] & GOO_CANVAS_TABLE_CHILD_FILL))
 	width = MIN (max_width, requested_width);
 
-      requested_height = goo_canvas_item_get_requested_height (child_item, cr,
-							       width);
-      if (requested_height >= 0.0)
-	child_data->requested_size[VERT] = requested_height;
+      iface = GOO_CANVAS_ITEM_GET_IFACE (child_item);
+
+      /* See if the child supports the new get_requested_area_for_width()
+	 method, which can handles the bounds being changed by the change
+	 in width & height. */
+      if (iface->get_requested_area_for_width)
+	{
+	  if (iface->get_requested_area_for_width (child_item, cr, width,
+						   &bounds))
+	    {
+	      /* Remember the requested position and size of the child. */
+	      child_data->requested_position[HORZ] = bounds.x1;
+	      child_data->requested_position[VERT] = bounds.y1;
+
+	      child_data->requested_size[HORZ] = bounds.x2 - bounds.x1;
+
+	      if (layout_data->integer_layout)
+		child_data->requested_size[VERT] = ceil (bounds.y2 - bounds.y1);
+	      else
+		child_data->requested_size[VERT] = bounds.y2 - bounds.y1;
+	    }
+	}
+      else if (iface->get_requested_height)
+	{
+	  requested_height = iface->get_requested_height (child_item, cr,
+							  width);
+	  if (requested_height >= 0.0)
+	    {
+	      child_data->requested_size[HORZ] = width;
+
+	      if (layout_data->integer_layout)
+		child_data->requested_size[VERT] = ceil (requested_height);
+	      else
+		child_data->requested_size[VERT] = requested_height;
+	    }
+	}
     }
 
   /* Now recalculate the requested heights of each row. */
diff --git a/src/goocanvastext.c b/src/goocanvastext.c
index 496089b..a1d88b1 100644
--- a/src/goocanvastext.c
+++ b/src/goocanvastext.c
@@ -488,8 +488,8 @@ goo_canvas_text_create_layout (GooCanvasItemSimpleData *simple_data,
 
       /* If the text width has been set, that width is used to do the alignment
 	 positioning. Otherwise the actual width is used. */
-      if (text_data->width > 0)
-	align_width = text_data->width;
+      if (layout_width > 0)
+	align_width = layout_width;
       else
 	align_width = logical_width;
 
@@ -540,7 +540,7 @@ goo_canvas_text_create_layout (GooCanvasItemSimpleData *simple_data,
       bounds->x1 = origin_x;
       bounds->y1 = origin_y;
 
-      if (text_data->width > 0)
+      if (layout_width > 0)
 	{
 	  /* If the text width has been set, and the alignment isn't
 	     PANGO_ALIGN_LEFT, we need to adjust for the difference between
@@ -744,29 +744,38 @@ goo_canvas_text_paint (GooCanvasItemSimple   *simple,
 }
 
 
-static gdouble
-goo_canvas_text_get_requested_height (GooCanvasItem	*item,
-				      cairo_t		*cr,
-				      gdouble            width)
+static gboolean
+goo_canvas_text_get_requested_area_for_width (GooCanvasItem	*item,
+					      cairo_t		*cr,
+					      gdouble            width,
+					      GooCanvasBounds	*requested_area)
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasText *text = (GooCanvasText*) item;
   GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
   PangoLayout *layout;
-  gdouble height;
+  cairo_matrix_t matrix;
+  double x_offset, y_offset;
 
   /* If we have a transformation besides a simple scale & translation, just
      return -1 as we can't adjust the height in that case. */
   if (simple_data->clip_path_commands
       || (simple_data->transform && (simple_data->transform->xy != 0.0
 				     || simple_data->transform->yx != 0.0)))
-    return -1;
+    return FALSE;
 
   cairo_save (cr);
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  /* Remove any current translation, to avoid the 16-bit cairo limit. */
+  cairo_get_matrix (cr, &matrix);
+  x_offset = matrix.x0;
+  y_offset = matrix.y0;
+  matrix.x0 = matrix.y0 = 0.0;
+  cairo_set_matrix (cr, &matrix);
+
   /* Convert the width from the parent's coordinate space. Note that we only
      need to support a simple scale operation here. */
   text->layout_width = width;
@@ -779,28 +788,49 @@ goo_canvas_text_get_requested_height (GooCanvasItem	*item,
 					  &simple->bounds, NULL, NULL);
   g_object_unref (layout);
 
-  if (priv->height < 0.0)
-    {
-      height = simple->bounds.y2 - simple->bounds.y1;
-    }
-  else
-    {
-      height = priv->height;
-      simple->bounds.y2 = simple->bounds.y1 + height;
-    }
+  /* If the height is set, use that. */
+  if (priv->height > 0.0)
+    simple->bounds.y2 = simple->bounds.y1 + priv->height;
 
-  /* Convert to the parent's coordinate space. As above, we only need to
-     support a simple scale operation here. */
-  if (simple_data->transform)
-    height *= simple_data->transform->yy;
+
+  /* Convert to device space. */
+  cairo_user_to_device (cr, &simple->bounds.x1, &simple->bounds.y1);
+  cairo_user_to_device (cr, &simple->bounds.x2, &simple->bounds.y2);
+
+  /* Add the translation back to the bounds. */
+  simple->bounds.x1 += x_offset;
+  simple->bounds.y1 += y_offset;
+  simple->bounds.x2 += x_offset;
+  simple->bounds.y2 += y_offset;
+
+  /* Restore the item's proper transformation matrix. */
+  matrix.x0 = x_offset;
+  matrix.y0 = y_offset;
+  cairo_set_matrix (cr, &matrix);
+
+  /* Convert back to user space. */
+  cairo_device_to_user (cr, &simple->bounds.x1, &simple->bounds.y1);
+  cairo_device_to_user (cr, &simple->bounds.x2, &simple->bounds.y2);
+
+
+  /* Copy the user bounds to the requested area. */
+  *requested_area = simple->bounds;
+
+  /* Convert to the parent's coordinate space. */
+  goo_canvas_item_simple_user_bounds_to_parent (simple, cr, requested_area);
 
   /* Convert the item's bounds to device space. */
   goo_canvas_item_simple_user_bounds_to_device (simple, cr, &simple->bounds);
 
+#if 0
+  g_print ("Width: %g Requested bounds: %g,%g - %g,%g\n",
+	   width, simple->bounds.x1, simple->bounds.y1,
+	   simple->bounds.x2, simple->bounds.y2);
+#endif
+
   cairo_restore (cr);
 
-  /* Return the new requested height of the text. */
-  return height;
+  return TRUE;
 }
 
 
@@ -861,7 +891,7 @@ goo_canvas_text_set_model    (GooCanvasItem      *item,
 static void
 canvas_item_interface_init (GooCanvasItemIface *iface)
 {
-  iface->get_requested_height = goo_canvas_text_get_requested_height;
+  iface->get_requested_area_for_width = goo_canvas_text_get_requested_area_for_width;
   iface->set_model            = goo_canvas_text_set_model;
 }
 



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