[glom] Print Layout: Create Standard: Move items to the next page when necessary.



commit 6d73c26daa5b88fcb3ceb0a47175eb99aa273fc9
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Oct 13 22:37:54 2011 +0200

    Print Layout: Create Standard: Move items to the next page when necessary.
    
    * glom/libglom/data_structure/layout/layoutitem.[h|cc]: Add
      set_print_layout_position_y() for convenience.
    * glom/print_layout/print_layout_utils.cc: create_standard(): Use
    move_fully_to_page().

 ChangeLog                                        |   11 ++-
 glom/libglom/data_structure/layout/layoutitem.cc |    9 +
 glom/libglom/data_structure/layout/layoutitem.h  |    4 +
 glom/print_layout/print_layout_utils.cc          |  178 +++++++++++-----------
 4 files changed, 112 insertions(+), 90 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b32df70..cf6b0ac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2011-10-13  Murray Cumming  <murrayc murrayc com>
 
+	Print Layout: Create Standard: Move items to the next page when necessary.
+
+	* glom/libglom/data_structure/layout/layoutitem.[h|cc]: Add 
+	set_print_layout_position_y() for convenience.
+	* glom/print_layout/print_layout_utils.cc: create_standard(): Use
+	move_fully_to_page().
+
+2011-10-13  Murray Cumming  <murrayc murrayc com>
+
 	Print Layout: Moved some code around.
 
 	* glom/print_layout/canvas_print_layout.[h|cc]: Moved get_page_for_y() and 
@@ -8,7 +17,7 @@
 
 2011-10-13  Murray Cumming  <murrayc murrayc com>
 
-	PrintLayout: Standard: Do not move to next page unnecessary.
+	PrintLayout: Standard: Do not move to next page unnecessarily.
 
 	* glom/print_layout/canvas_print_layout.cc: get_page_for_y(): Correct this
   calculation.
diff --git a/glom/libglom/data_structure/layout/layoutitem.cc b/glom/libglom/data_structure/layout/layoutitem.cc
index f46928b..521f4c2 100644
--- a/glom/libglom/data_structure/layout/layoutitem.cc
+++ b/glom/libglom/data_structure/layout/layoutitem.cc
@@ -194,6 +194,15 @@ void LayoutItem::set_print_layout_position(double x, double y, double width, dou
   m_positions->m_height = height;
 }
 
+void LayoutItem::set_print_layout_position_y(double y)
+{
+  if(!m_positions && (y == 0))
+    return; //Don't bother instantiating the positions instance if everything is still 0.
+
+  instantiate_positions();
+
+  m_positions->m_y = y;
+}
 
 void LayoutItem::set_print_layout_split_across_pages(bool split)
 {
diff --git a/glom/libglom/data_structure/layout/layoutitem.h b/glom/libglom/data_structure/layout/layoutitem.h
index 5ec3d52..1a0472c 100644
--- a/glom/libglom/data_structure/layout/layoutitem.h
+++ b/glom/libglom/data_structure/layout/layoutitem.h
@@ -62,7 +62,11 @@ public:
 
   /// This is used only for the print layouts.
   void set_print_layout_position(double x, double y, double width, double height);
+  
+  /// This is used only for the print layouts.
+  void set_print_layout_position_y(double y);
 
+  //TODO: Do we use this? Do we want to?
   /// This is used only for the print layouts.
   void set_print_layout_split_across_pages(bool split = true);
 
diff --git a/glom/print_layout/print_layout_utils.cc b/glom/print_layout/print_layout_utils.cc
index a2264a9..df296fa 100644
--- a/glom/print_layout/print_layout_utils.cc
+++ b/glom/print_layout/print_layout_utils.cc
@@ -97,17 +97,79 @@ static void get_page_y_start_and_end(const Glib::RefPtr<const Gtk::PageSetup>& p
 }
 
 
-static void create_standard(const sharedptr<const LayoutGroup>& layout_group, const sharedptr<LayoutGroup>& print_layout_group, const Glib::RefPtr<const Gtk::PageSetup>& page_setup, double x, double& y, guint& page_number)
+static double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, double y, double height)
+{
+  double top_margin = 0;
+  double bottom_margin = 0;
+  const double page_height = get_page_height(page_setup, units, top_margin, bottom_margin);
+
+  //Ignore items that would not overlap even if they had the same y:
+  //Note that we try to keep an extra GRID_GAP from the edge of the margin:
+  const double usable_page_height = page_height - top_margin - bottom_margin - GRID_GAP * 2;
+  if(height > usable_page_height)
+    return y; //It will always be in a margin because it is so big. We could never move it somewhere where it would not be.
+
+  const guint current_page = PrintLayoutUtils::get_page_for_y(page_setup, units, y);
+  const double usable_page_start = current_page * page_height + top_margin + GRID_GAP;
+  //std::cout << G_STRFUNC << ": debug: current_page=" << current_page << ", usable_page_start =" << usable_page_start << std::endl;
+
+  if(y < usable_page_start) //If it is in the top margin:
+  {
+    //Move it to the end of the top margin:
+    y = usable_page_start;
+  }
+
+  const double usable_page_end = (current_page + 1) * page_height - bottom_margin - GRID_GAP;
+  if((y + height) > usable_page_end) //If it is in the top margin:
+  {
+    //Move it to the start of the next page:
+    y = (current_page + 1) * page_height + top_margin + GRID_GAP;
+  }
+
+  return y;
+}
+
+double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const Glib::RefPtr<CanvasLayoutItem>& item)
+{
+  double x = 0;
+  double y = 0;
+  item->get_xy(x, y);
+  
+  double width = 0;
+  double height = 0;
+  item->get_width_height(width, height);
+  
+  const double y_new = move_fully_to_page(page_setup, units, y, height);
+  if(y_new != y)
+    item->set_xy(x, y_new);
+    
+  return y_new;
+}
+
+/*
+static double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const sharedptr<LayoutItem>& item)
+{
+  double x = 0;
+  double y = 0;
+  double width = 0;
+  double height = 0;
+  item->get_print_layout_position(x, y, width, height);
+  
+  const double y_new = move_fully_to_page(page_setup, units, y, height);
+  if(y_new != y)
+    item->set_print_layout_position(x, y_new, width, height);
+    
+  return y_new;
+}
+*/
+
+static void create_standard(const sharedptr<const LayoutGroup>& layout_group, const sharedptr<LayoutGroup>& print_layout_group, const Glib::RefPtr<const Gtk::PageSetup>& page_setup, double x, double& y)
 {
   if(!layout_group || !print_layout_group)
   {
     return;
   }
 
-  double min_y = 0; //ignored;
-  double max_y = 0;
-  get_page_y_start_and_end(page_setup, page_number, min_y, max_y);
-
   const double gap = GRID_GAP;
 
   const Gtk::Unit units = get_units();
@@ -125,18 +187,11 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
     text->set_text(title);
     text->m_formatting.set_text_format_font("Sans Bold 10");
 
+    y = move_fully_to_page(page_setup, units, y, field_height);
     text->set_print_layout_position(x, y, item_width, field_height); //TODO: Enough and no more.
     y += field_height + gap; //padding.
 
     print_layout_group->add_item(text);
-
-    //Start on the next page, if necessary:
-    //TODO: Add a page if necessary:
-    if( y >= max_y )
-    {
-      page_number += 1;
-      get_page_y_start_and_end(page_setup, page_number, y, max_y);
-    }
   }
 
   //Deal with a portal group: 
@@ -153,19 +208,12 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
 
     //Set an initial default height, though this will be changed
     //when we fill it with data:
+    y = move_fully_to_page(page_setup, units, y, field_height);
     portal_clone->set_print_layout_position(x, y, item_width, field_height);
     y += field_height + gap; //padding.
 
     print_layout_group->add_item(portal_clone);
 
-    //Start on the next page, if necessary:
-    //TODO: Add a page if necessary:
-    if( y >= max_y )
-    {
-      page_number += 1;
-      get_page_y_start_and_end(page_setup, page_number, y, max_y);
-    }
-
     return;
   }
 
@@ -180,22 +228,24 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
     const sharedptr<const LayoutGroup> group = sharedptr<const LayoutGroup>::cast_dynamic(item);
     if(group && !portal)
     {
-      //Recurse: //TODO: Handle portals separately:
-      create_standard(group, print_layout_group, page_setup, x, y, page_number);
+      //Recurse:
+      create_standard(group, print_layout_group, page_setup, x, y);
     }
     else
     {
       //Add field titles, if necessary:
+      sharedptr<LayoutItem_Text> text_title;
       const double title_width = ITEM_WIDTH_WIDE; //TODO: Calculate it based on the widest in the column. Or just halve the column to start.
       const sharedptr<const LayoutItem_Field> field = sharedptr<const LayoutItem_Field>::cast_dynamic(item);
       if(field)
       {
-        sharedptr<LayoutItem_Text> text = sharedptr<LayoutItem_Text>::create();
-        text->set_text(field->get_title_or_name() + ":");
-        text->set_print_layout_position(x, y, title_width, field_height); //TODO: Enough and no more.
-        text->m_formatting.set_text_format_font("Sans 10");
+        text_title = sharedptr<LayoutItem_Text>::create();
+        text_title->set_text(field->get_title_or_name() + ":");
+        y = move_fully_to_page(page_setup, units, y, field_height);
+        text_title->set_print_layout_position(x, y, title_width, field_height); //TODO: Enough and no more.
+        text_title->m_formatting.set_text_format_font("Sans 10");
 
-        print_layout_group->add_item(text);
+        print_layout_group->add_item(text_title);
       }
 
       //Add the item, such as a field:
@@ -206,18 +256,16 @@ static void create_standard(const sharedptr<const LayoutGroup>& layout_group, co
         item_x += (title_width + gap);
 
       const double field_width = item_width - title_width - gap;
+      y = move_fully_to_page(page_setup, units, y, field_height); //TODO: Move the title down too, if this was moved.
       clone->set_print_layout_position(item_x, y, field_width, field_height); //TODO: Enough and no more.
+      
+      //Make sure that the title is still aligned, even if this was moved by move_fully_to_page().
+      if(text_title)
+        text_title->set_print_layout_position_y(y);
+      
       y += field_height + gap; //padding.
 
       print_layout_group->add_item(clone);
-
-      //Start on the next page, if necessary:
-      //TODO: Add a page if necessary:
-      if( y >= max_y )
-      {
-        page_number += 1;
-        get_page_y_start_and_end(page_setup, page_number, y, max_y);
-      }
     }
   }
 }
@@ -234,56 +282,6 @@ guint get_page_for_y(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::
   return pages_integral;
 }
 
-double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const Glib::RefPtr<CanvasLayoutItem>& item)
-{
-  double top_margin = 0;
-  double bottom_margin = 0;
-  const double page_height = get_page_height(page_setup, units, top_margin, bottom_margin);
-
-  double x = 0;
-  double y = 0;
-  item->get_xy(x, y);
-  std::cout << G_STRFUNC << ": y=" << y << std::endl;
-  
-  //Ignore items that would not overlap even if they had the same y:
-  double width = 0;
-  double height = 0;
-  item->get_width_height(width, height);
-
-  const double usable_page_height = page_height - top_margin - bottom_margin;
-  if(height > usable_page_height)
-    return y; //It will always be in a margin because it is so big. We could never move it somewhere where it would not be.
-
-  bool moved = false;
-  const guint current_page = PrintLayoutUtils::get_page_for_y(page_setup, units, y);
-  const double usable_page_start = current_page * page_height + top_margin;
-  //std::cout << G_STRFUNC << ": debug: current_page=" << current_page << ", usable_page_start =" << usable_page_start << std::endl;
-
-  if(y < usable_page_start) //If it is in the top margin:
-  {
-    //Move it to the end of the top margin:
-    y = usable_page_start;
-    moved = true;
-  }
-
-  const double usable_page_end = (current_page + 1) * page_height - bottom_margin;
-  if((y + height) > usable_page_end) //If it is in the top margin:
-  {
-    //Move it to the start of the next page:
-    y = (current_page + 1) * page_height + top_margin;
-    moved = false;
-  }
-
-  if(moved)
-    item->set_xy(x, y);
-    
-  std::cout << G_STRFUNC << ": y moved=" << y << std::endl;
-  
-
-  return y;
-}
-
-
 sharedptr<PrintLayout> create_standard(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, const Glib::ustring& table_name, const Document* document)
 {
   sharedptr<PrintLayout> print_layout = sharedptr<PrintLayout>::create();  
@@ -291,8 +289,7 @@ sharedptr<PrintLayout> create_standard(const Glib::RefPtr<const Gtk::PageSetup>&
   //Start inside the border, on the next grid line:
   double y = 0;
   double max_y = 0; //ignored
-  guint page_number = 0;
-  get_page_y_start_and_end(page_setup, page_number, y, max_y);
+  get_page_y_start_and_end(page_setup, 0, y, max_y);
   
   double x = 0;
   double x_border = 0;
@@ -326,10 +323,13 @@ sharedptr<PrintLayout> create_standard(const Glib::RefPtr<const Gtk::PageSetup>&
     if(!group)
       continue;
 
-    create_standard(group, print_layout->m_layout_group, page_setup, x, y, page_number);
+    create_standard(group, print_layout->m_layout_group, page_setup, x, y);
   }
 
   //Add extra pages if necessary:
+  //TODO: y is probably _after_ the last item, not exactly at the bottom of the last item,
+  //so this could lead to an extra blank page.
+  const guint page_number = get_page_for_y(page_setup, get_units(), y);
   if(page_number >= print_layout->get_page_count())
   {
     print_layout->set_page_count(page_number + 1);



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