[glom] Print Layout: Related Records: Expand according to min/max rows count.



commit 80944392a44b96a95e30bfe5a244acc349c3f52f
Author: Murray Cumming <murrayc murrayc com>
Date:   Wed Oct 12 01:14:39 2011 +0200

    Print Layout: Related Records: Expand according to min/max rows count.
    
    * glom/print_layout/canvas_layout_item.[h|cc]:
    Moved get_canvas_table_cell_child() here from CanvasPrintLayout.
    create_canvas_item_for_layout_item(): Move the table-child creation
    code into add_portal_rows_if_necessary().
    * glom/print_layout/canvas_print_layout.[h|cc]: fill_with_data_portal():
    Add rows, up to the maximum, according to the number of database rows.
    * glom/print_layout/print_layout_utils.cc: create_standard():
    Set a simple default height for one row, but set a min of 1 and a max
    of 100 so it will expand later.

 ChangeLog                                          |   14 ++
 .../data_structure/layout/layoutitem_portal.cc     |    4 +
 glom/print_layout/canvas_layout_item.cc            |  223 +++++++++++++-------
 glom/print_layout/canvas_layout_item.h             |   11 +
 glom/print_layout/canvas_print_layout.cc           |   68 +++----
 glom/print_layout/canvas_print_layout.h            |    2 -
 glom/print_layout/print_layout_utils.cc            |   18 +-
 7 files changed, 213 insertions(+), 127 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 844237d..cce74dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-10-12  Murray Cumming  <murrayc murrayc com>
+
+	Print Layout: Related Records: Expand according to min/max rows count.
+
+	* glom/print_layout/canvas_layout_item.[h|cc]: 
+	Moved get_canvas_table_cell_child() here from CanvasPrintLayout.
+	create_canvas_item_for_layout_item(): Move the table-child creation 
+	code into add_portal_rows_if_necessary().
+	* glom/print_layout/canvas_print_layout.[h|cc]: fill_with_data_portal():
+	Add rows, up to the maximum, according to the number of database rows.
+	* glom/print_layout/print_layout_utils.cc: create_standard():
+	Set a simple default height for one row, but set a min of 1 and a max 
+	of 100 so it will expand later.
+
 2011-10-11  Murray Cumming  <murrayc murrayc com>
 
 	Update the example files for the portal rows count change.
diff --git a/glom/libglom/data_structure/layout/layoutitem_portal.cc b/glom/libglom/data_structure/layout/layoutitem_portal.cc
index 1af0fa8..339bdf6 100644
--- a/glom/libglom/data_structure/layout/layoutitem_portal.cc
+++ b/glom/libglom/data_structure/layout/layoutitem_portal.cc
@@ -193,6 +193,10 @@ void LayoutItem_Portal::set_rows_count(gulong rows_count_min, gulong rows_count_
 {
   m_rows_count_min = rows_count_min;
   m_rows_count_max = rows_count_max;
+
+  //Keep the values sane:
+  if(m_rows_count_max < m_rows_count_min)
+    m_rows_count_max = m_rows_count_min;
 }
 
 double LayoutItem_Portal::get_print_layout_row_line_width() const
diff --git a/glom/print_layout/canvas_layout_item.cc b/glom/print_layout/canvas_layout_item.cc
index 02c5395..e5ce553 100644
--- a/glom/print_layout/canvas_layout_item.cc
+++ b/glom/print_layout/canvas_layout_item.cc
@@ -163,6 +163,7 @@ void CanvasLayoutItem::set_layout_item(const sharedptr<LayoutItem>& layout_item)
   }
 }
 
+//TODO: Remove this?
 int CanvasLayoutItem::get_rows_count_for_portal(const sharedptr<const LayoutItem_Portal>& portal, double& row_height)
 {
   if(!portal)
@@ -182,6 +183,7 @@ int CanvasLayoutItem::get_rows_count_for_portal(const sharedptr<const LayoutItem
   const double max_rows_fraction = total_height / row_height;
   double max_rows = 0;
   modf(max_rows_fraction, &max_rows);
+  std::cout << "debug: max_rows=" << max_rows << ", for total_height=" << total_height << ", row_height=" << row_height << std::endl;
 
   return max_rows;
 }
@@ -284,83 +286,10 @@ Glib::RefPtr<CanvasItemMovable> CanvasLayoutItem::create_canvas_item_for_layout_
               portal->get_print_layout_column_line_width(),
               portal->get_print_layout_line_color());
 
-            //Show as many rows as can fit in the height.
-            double row_height = 0;
-            const int max_rows = get_rows_count_for_portal(portal, row_height);
-            //std::cout << "DEBUG: max_rows=" << max_rows << ", row_height=" << row_height << std::endl;
-
-            const LayoutGroup::type_list_items child_items = portal->get_items();
-
-            for(guint row = 0; row < (guint)max_rows; ++row)
-            {
-              guint col = 0;
-              const guint num_cols = child_items.size();
-              bool something_expanded = false;
-              for(LayoutGroup::type_list_items::const_iterator iter = child_items.begin(); iter != child_items.end(); ++iter)
-              {
-                sharedptr<LayoutItem> layout_item = *iter;
-
-                //We use create_canvas_item_for_layout_item() instead of just
-                //creating another CanvasLayoutItem, because that would be a group,
-                //but goocanvas cannot yet support Groups inside Tables. murrayc.
-                //TODO: Bug number.
-                Glib::RefPtr<CanvasItemMovable> cell = create_canvas_item_for_layout_item(layout_item);
-                Glib::RefPtr<Goocanvas::Item> cell_as_item = CanvasItemMovable::cast_to_item(cell);
-
-                if(cell && cell_as_item)
-                {
-                  const guint width = layout_item->get_display_width();
-                  bool expand = (width == 0);
-                  
-                  //If this is the last item, and no other item has expanded,
-                  //let this one expand,
-                  //Otherwise, we could allocate less space than the table has left.
-                  //TODO: Prevent the user from allocating _more_ space than the table has.
-                  if(!something_expanded && (col == (num_cols - 1)))
-                  {
-                    expand = true;
-                  }
-                  
-                  if(expand)
-                  {
-                    //Let the table allocate the width automatically:
-                    
-                    cell->set_width_height(-1, row_height);
-                    canvas_item->attach(cell_as_item,
-                      col /* left_attach */, col + 1 /* right_attach */,
-                      row /* top_attach */, row + 1 /* right_attach */,
-                      (Gtk::AttachOptions)(Gtk::FILL | Gtk::EXPAND), (Gtk::AttachOptions)(Gtk::FILL | Gtk::EXPAND));
-                      
-                    something_expanded = true;
-                  }
-                  else
-                  {
-                    //Enforce a width:
-                    
-                    //TODO: Add/Remove rows when resizing, instead of resizing the rows:
-                    cell->set_width_height(width, row_height);
-
-                    canvas_item->attach(cell_as_item,
-                      col /* left_attach */, col + 1 /* right_attach */,
-                      row /* top_attach */, row + 1 /* right_attach */,
-                      (Gtk::FILL), (Gtk::AttachOptions)(Gtk::FILL | Gtk::EXPAND));
-                      
-                    //Add a second item (an invisible rect) to make sure that the size is really used:
-                    Glib::RefPtr<Goocanvas::Rect> rect = 
-                      Goocanvas::Rect::create(0, 0, width, row_height);
-                    //TODO: Find out why this doesn't work: rect->property_stroke_pattern() = Cairo::RefPtr<Cairo::Pattern>();
-                    g_object_set(rect->gobj(), "stroke-pattern", (void*)0, (void*)0);
-                     
-                    canvas_item->attach(rect,
-                      col /* left_attach */, col + 1 /* right_attach */,
-                      row /* top_attach */, row + 1 /* right_attach */,
-                      Gtk::SHRINK, Gtk::SHRINK);
-                  }
-                }
-
-                ++col;
-              }
-            }
+            gulong rows_count_min = 0;
+            gulong rows_count_max = 0;
+            portal->get_rows_count(rows_count_min, rows_count_max);
+            add_portal_rows_if_necessary(canvas_item, portal, rows_count_min);
 
             child = canvas_item;
             child_item = canvas_item;
@@ -381,6 +310,146 @@ Glib::RefPtr<CanvasItemMovable> CanvasLayoutItem::create_canvas_item_for_layout_
   return child;
 }
 
+
+Glib::RefPtr<Goocanvas::Item> CanvasLayoutItem::get_canvas_table_cell_child(const Glib::RefPtr<Goocanvas::Table>& table, int row, int col)
+{
+  Glib::RefPtr<Goocanvas::Item> result;
+
+  if(!table)
+    return result;
+
+  const int count = table->get_n_children();
+  for(int i = 0; i < count; ++i)
+  {
+    Glib::RefPtr<Goocanvas::Item> child = table->get_child(i);
+    if(!child)
+      continue;
+
+    int column_value = 0;
+    table->get_child_property(child, "column", column_value);
+    int row_value = 0;
+    table->get_child_property(child, "row", row_value);
+
+    //This assumes that all items occupy only one cell:
+    if( (column_value == col) &&
+        (row_value == row) )
+    {
+      return child;
+    }
+  }
+
+  return result;
+}
+
+void CanvasLayoutItem::add_portal_rows_if_necessary(guint rows_count)
+{
+  Glib::RefPtr<CanvasItemMovable> child = get_child();
+  Glib::RefPtr<CanvasTableMovable> canvas_table = 
+    Glib::RefPtr<CanvasTableMovable>::cast_dynamic(child);
+  if(!canvas_table)
+    return;
+
+  sharedptr<LayoutItem_Portal> portal = 
+    sharedptr<LayoutItem_Portal>::cast_dynamic(get_layout_item());
+  if(!portal)
+  {
+    std::cerr << G_STRFUNC << ": The layout item was not a portal." << std::endl;
+    return;
+  }
+
+  add_portal_rows_if_necessary(canvas_table, portal, rows_count);
+}
+
+void CanvasLayoutItem::add_portal_rows_if_necessary(const Glib::RefPtr<CanvasTableMovable>& canvas_table, const sharedptr<LayoutItem_Portal>& portal, guint rows_count)
+{
+  const double row_height = portal->get_print_layout_row_height();
+  const LayoutGroup::type_list_items child_items = portal->get_items();
+
+  for(guint row = 0; row < rows_count; ++row)
+  {
+    guint col = 0;
+    const guint num_cols = child_items.size();
+    bool something_expanded = false;
+    for(LayoutGroup::type_list_items::const_iterator iter = child_items.begin(); iter != child_items.end(); ++iter)
+    {
+      //std::cout << "  row=" << row << ", col=" << col << std::endl;
+      sharedptr<LayoutItem> layout_item = *iter;
+
+      //Check if a child already exists:
+      Glib::RefPtr<Goocanvas::Item> existing_child = 
+        get_canvas_table_cell_child(canvas_table, row, col);
+      if(existing_child)
+      {
+        //std::cout << "    existing child" << std::endl;
+        col++;
+        continue;
+      }
+
+      //We use create_canvas_item_for_layout_item() instead of just
+      //creating another CanvasLayoutItem, because that would be a group,
+      //but goocanvas cannot yet support Groups inside Tables. murrayc.
+      //TODO: Bug number.
+      Glib::RefPtr<CanvasItemMovable> cell = create_canvas_item_for_layout_item(layout_item);
+      Glib::RefPtr<Goocanvas::Item> cell_as_item = CanvasItemMovable::cast_to_item(cell);
+
+      if(cell && cell_as_item)
+      {
+        std::cout << "    creating child" << std::endl;
+        
+        const guint width = layout_item->get_display_width();
+        bool expand = (width == 0);
+        
+        //If this is the last item, and no other item has expanded,
+        //let this one expand,
+        //Otherwise, we could allocate less space than the table has left.
+        //TODO: Prevent the user from allocating _more_ space than the table has.
+        if(!something_expanded && (col == (num_cols - 1)))
+        {
+          expand = true;
+        }
+        
+        if(expand)
+        {
+            //Let the table allocate the width automatically:
+
+            cell->set_width_height(-1, row_height);
+            canvas_table->attach(cell_as_item,
+              col /* left_attach */, col + 1 /* right_attach */,
+              row /* top_attach */, row + 1 /* right_attach */,
+              (Gtk::AttachOptions)(Gtk::FILL | Gtk::EXPAND), (Gtk::AttachOptions)(Gtk::FILL | Gtk::EXPAND));
+  
+            something_expanded = true;
+        }
+        else
+        {
+            //Enforce a width:
+
+            //TODO: Add/Remove rows when resizing, instead of resizing the rows:
+            cell->set_width_height(width, row_height);
+
+            canvas_table->attach(cell_as_item,
+              col /* left_attach */, col + 1 /* right_attach */,
+              row /* top_attach */, row + 1 /* right_attach */,
+              (Gtk::FILL), (Gtk::AttachOptions)(Gtk::FILL | Gtk::EXPAND));
+  
+            //Add a second item (an invisible rect) to make sure that the size is really used:
+            Glib::RefPtr<Goocanvas::Rect> rect = 
+              Goocanvas::Rect::create(0, 0, width, row_height);
+            //TODO: Find out why this doesn't work: rect->property_stroke_pattern() = Cairo::RefPtr<Cairo::Pattern>();
+            g_object_set(rect->gobj(), "stroke-pattern", (void*)0, (void*)0);
+ 
+            canvas_table->attach(rect,
+              col /* left_attach */, col + 1 /* right_attach */,
+              row /* top_attach */, row + 1 /* right_attach */,
+              Gtk::SHRINK, Gtk::SHRINK);
+        }
+      }
+
+      ++col;
+    }
+  }
+}
+
 void CanvasLayoutItem::set_db_data(const Gnome::Gda::Value& value)
 {
   sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(m_layout_item);
diff --git a/glom/print_layout/canvas_layout_item.h b/glom/print_layout/canvas_layout_item.h
index 954243b..7db7c08 100644
--- a/glom/print_layout/canvas_layout_item.h
+++ b/glom/print_layout/canvas_layout_item.h
@@ -24,11 +24,13 @@
 #include <glom/utility_widgets/canvas/canvas_group_resizable.h>
 #include <libglom/data_structure/layout/layoutitem_withformatting.h>
 #include <libgdamm/value.h>
+#include <goocanvasmm/table.h>
 
 namespace Glom
 {
 
 class CanvasTextMovable;
+class CanvasTableMovable;
 class FieldFormatting;
 class LayoutItem_Portal;
 
@@ -67,12 +69,21 @@ public:
    */
   void update_layout_position_from_canvas();
 
+  /* Add table child items if any are missing,
+   * for instance if the table has been made bigger.
+   */
+  void add_portal_rows_if_necessary(guint rows_count);
+
+  static Glib::RefPtr<Goocanvas::Item> get_canvas_table_cell_child(const Glib::RefPtr<Goocanvas::Table>& table, int row, int col); //TODO: Add this to Goocanvas::Table.
+
 private:
   /// Create the appropriate inner canvas item to represent the layout item.
   static Glib::RefPtr<CanvasItemMovable> create_canvas_item_for_layout_item(const sharedptr<LayoutItem>& layout_item);
 
   static void apply_formatting(const Glib::RefPtr<CanvasTextMovable>& canvas_item, const sharedptr<const LayoutItem_WithFormatting>& layout_item);
   
+  static void add_portal_rows_if_necessary(const Glib::RefPtr<CanvasTableMovable>& canvas_table, const sharedptr<LayoutItem_Portal>& portal, guint rows_count);
+
   void on_resized();
 
   sharedptr<LayoutItem> m_layout_item;
diff --git a/glom/print_layout/canvas_print_layout.cc b/glom/print_layout/canvas_print_layout.cc
index 6927b9d..fe3a43e 100644
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@ -894,17 +894,35 @@ void Canvas_PrintLayout::fill_with_data_portal(const Glib::RefPtr<CanvasLayoutIt
   found_set.m_table_name = portal->get_table_used(Glib::ustring() /* parent table_name, not used. */);
   set_found_set_where_clause_for_portal(found_set, portal, foreign_key_value);
 
-  Glib::RefPtr<Gnome::Gda::SqlBuilder> sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name, fields_shown, found_set.m_where_clause, found_set.m_extra_join, found_set.m_sort_clause);
+  const Glib::RefPtr<Gnome::Gda::SqlBuilder> sql_query = Utils::build_sql_select_with_where_clause(found_set.m_table_name, fields_shown, found_set.m_where_clause, found_set.m_extra_join, found_set.m_sort_clause);
   //std::cout << "DEBUG: sql_query=" << sql_query << std::endl;
-  Glib::RefPtr<Gnome::Gda::DataModel> datamodel = DbUtils::query_execute_select(sql_query);
+  const Glib::RefPtr<const Gnome::Gda::DataModel> datamodel = DbUtils::query_execute_select(sql_query);
   if(!(datamodel))
     return;
 
-  const int db_rows_count = datamodel->get_n_rows();
+  const int db_rows_count = datamodel->get_n_rows(); //TODO: Performance? COUNT them instead?
   const int db_columns_count = datamodel->get_n_columns();
 
-  double row_height_ignored = 0;
-  const int rows_count = CanvasLayoutItem::get_rows_count_for_portal(portal, row_height_ignored);
+  //Show as many rows as needed, but not more than the maximum:
+  gulong rows_count_min = 0;
+  gulong rows_count_max = 0;
+  portal->get_rows_count(rows_count_min, rows_count_max);
+  int rows_count = std::min((int)rows_count_max, db_rows_count);
+  //Do not use less than the minimum:
+  rows_count = std::max(rows_count, (int)rows_count_min);
+
+  // TODO: Remove this method and/or change it to recalc the min when changing the height:
+  //CanvasLayoutItem::get_rows_count_for_portal(portal, row_height_ignored);
+  const double portal_height = rows_count * portal->get_print_layout_row_height();
+
+  double old_width = 0;
+  double old_height = 0;
+  canvas_item->get_width_height(old_width, old_height);
+  canvas_item->set_width_height(old_width, portal_height);
+  std::cout << G_STRFUNC << ": portal_height = " << portal_height << ", for rows_count=" << rows_count << std::endl;
+  canvas_item->add_portal_rows_if_necessary(rows_count);
+  //TODO: Move everything else down.
+
   const int cols_count = child_layout_items.size();
 
   //Set the DB value for each cell:
@@ -915,9 +933,13 @@ void Canvas_PrintLayout::fill_with_data_portal(const Glib::RefPtr<CanvasLayoutIt
     for(int col = 0; col < cols_count; ++col)
     {
       //Glib::RefPtr<Goocanvas::Item> canvas_child = base_item->get_cell_child(row, col); //TODO: Add this to Goocanvas::Table.
-      Glib::RefPtr<Goocanvas::Item> canvas_child = get_canvas_table_cell_child(canvas_table, row, col); //TODO: Add this to Goocanvas::Table.
+      Glib::RefPtr<Goocanvas::Item> canvas_child = 
+        CanvasLayoutItem::get_canvas_table_cell_child(canvas_table, row, col); //TODO: Add this to Goocanvas::Table.
       if(!canvas_child)
-        std::cerr << G_STRFUNC << ": canvas_child is NULL." << std::endl;
+      {
+        std::cerr << G_STRFUNC << ": canvas_child is NULL for row=" << row << ", col=" << col << std::endl;
+        continue;
+      }
 
       if(iter_child_layout_items == child_layout_items.end())
         continue;
@@ -1016,38 +1038,6 @@ void Canvas_PrintLayout::set_grid_gap(double gap)
     m_bounds_group->lower();
 }
 
-Glib::RefPtr<Goocanvas::Item> Canvas_PrintLayout::get_canvas_table_cell_child(const Glib::RefPtr<Goocanvas::Table>& table, int row, int col)
-{
-  Glib::RefPtr<Goocanvas::Item> result;
-
-  if(!table)
-    return result;
-
-  const int count = table->get_n_children();
-  for(int i = 0; i < count; ++i)
-  {
-    Glib::RefPtr<Goocanvas::Item> child = table->get_child(i);
-    if(!child)
-      continue;
-
-    int column_value = 0;
-    table->get_child_property(child, "column", column_value);
-    int row_value = 0;
-    table->get_child_property(child, "row", row_value);
-
-    //This assumes that all items occupy only one cell:
-    if( (column_value == col) &&
-        (row_value == row) )
-    {
-      return child;
-    }
-  }
-
-  return result;
-}
-
-
-
 Base_DB::type_vecConstLayoutFields Canvas_PrintLayout::get_portal_fields_to_show(const sharedptr<LayoutItem_Portal>& portal)
 {
   const Document* document = get_document();
diff --git a/glom/print_layout/canvas_print_layout.h b/glom/print_layout/canvas_print_layout.h
index 4abea0f..50c1f84 100644
--- a/glom/print_layout/canvas_print_layout.h
+++ b/glom/print_layout/canvas_print_layout.h
@@ -103,8 +103,6 @@ private:
   void fill_with_data(const Glib::RefPtr<Goocanvas::Group>& canvas_group, const FoundSet& found_set);
   void fill_with_data_portal(const Glib::RefPtr<CanvasLayoutItem>& canvas_item, const Gnome::Gda::Value& foreign_key_value);
   static void set_canvas_item_field_value(const Glib::RefPtr<Goocanvas::Item>& canvas_item, const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& value);
-
-  static Glib::RefPtr<Goocanvas::Item> get_canvas_table_cell_child(const Glib::RefPtr<Goocanvas::Table>& table, int row, int col); //TODO: Add this to Goocanvas::Table.
   
   type_vecConstLayoutFields get_portal_fields_to_show(const sharedptr<LayoutItem_Portal>& portal);
 
diff --git a/glom/print_layout/print_layout_utils.cc b/glom/print_layout/print_layout_utils.cc
index 8312163..991bd42 100644
--- a/glom/print_layout/print_layout_utils.cc
+++ b/glom/print_layout/print_layout_utils.cc
@@ -115,15 +115,15 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
     sharedptr<LayoutItem_Portal> portal_clone = glom_sharedptr_clone(portal);
     portal_clone->set_print_layout_row_height(field_height); //Otherwise it will be 0, which is useless.
 
-    double height = ITEM_HEIGHT;
-    gulong rows_count_min = 0;
-    gulong rows_count_max = 0;
-    portal->get_rows_count(rows_count_min, rows_count_max);
-    if(rows_count_min)
-      height = ITEM_HEIGHT * rows_count_min; //TODO: Expand to max when necessary.
-
-    portal_clone->set_print_layout_position(x, y, item_width, height); //TODO: Enough and no more.
-    y += height + gap; //padding.
+    //We ignore the rows count for the details layout's portal,
+    //because that is only suitable for the on-screen layout,
+    //and because, on the print layout, we want to show (almost) all rows: 
+    portal_clone->set_rows_count(1 /* min */, 100 /* max */);
+
+    //Set an initial default height, though this will be changed
+    //when we fill it with data:
+    portal_clone->set_print_layout_position(x, y, item_width, field_height);
+    y += field_height + gap; //padding.
 
     print_layout_group->add_item(portal_clone);
 



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