[glom] Print Layout: Avoid grouping items at the tops of pages.



commit ec191a4966789fd936784ba0539a35897c6dba32
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Oct 14 12:30:17 2011 +0200

    Print Layout: Avoid grouping items at the tops of pages.
    
    * glom/print_layout/print_layout_utils.[h|cc]: move_fully_to_page():
    Change this to needs_move_fully_to_page(), so we can decide later how
    much to move the items.
    * glom/print_layout/canvas_print_layout.[h|cc]: move_items_below_item():
    Rename to move_items_down(), not taking an item, and ignoring the x
    dimension, moving everything down.
    Remember the highest item that needs moving down more, because it
    is in a page margin, then move everything below it down by the same
    offset. Keep doing that until no items are in margins, gradually adding
    pages. This is a simple form of pagination, and not a particularly
    efficient one.

 ChangeLog                                |   16 +++++++
 glom/print_layout/canvas_print_layout.cc |   70 +++++++++++++++++++++---------
 glom/print_layout/canvas_print_layout.h  |    6 +-
 glom/print_layout/print_layout_utils.cc  |   46 ++++++++++++-------
 glom/print_layout/print_layout_utils.h   |   10 +++--
 5 files changed, 103 insertions(+), 45 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b76377d..7c3a3eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2011-10-14  Murray Cumming  <murrayc murrayc com>
 
+	Print Layout: Avoid grouping items at the tops of pages.
+
+	* glom/print_layout/print_layout_utils.[h|cc]: move_fully_to_page():
+	Change this to needs_move_fully_to_page(), so we can decide later how
+	much to move the items.
+	* glom/print_layout/canvas_print_layout.[h|cc]: move_items_below_item():
+	Rename to move_items_down(), not taking an item, and ignoring the x
+	dimension, moving everything down.
+	Remember the highest item that needs moving down more, because it 
+	is in a page margin, then move everything below it down by the same 
+	offset. Keep doing that until no items are in margins, gradually adding 
+	pages. This is a simple form of pagination, and not a particularly 
+	efficient one.
+
+2011-10-14  Murray Cumming  <murrayc murrayc com>
+
 	Print Layout: Another expansion fixes.
 
 	* glom/print_layout/print_layout_utils.[h|cc]: move_fully_to_page():
diff --git a/glom/print_layout/canvas_print_layout.cc b/glom/print_layout/canvas_print_layout.cc
index 6741083..ad6118f 100644
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@ -931,7 +931,7 @@ void Canvas_PrintLayout::fill_with_data_portal(const Glib::RefPtr<CanvasLayoutIt
   double y = 0;
   canvas_item->get_xy(x, y);
   const double offset = portal_height - old_height;
-  move_items_below_item(canvas_item, y + old_height, offset);
+  move_items_down(y + old_height, offset);
 
   canvas_item->add_portal_rows_if_necessary(rows_count);
   //TODO: Move everything else down.
@@ -1188,18 +1188,16 @@ Goocanvas::Bounds Canvas_PrintLayout::get_page_bounds(guint page_num) const
   return bounds;
 }
 
-void Canvas_PrintLayout::move_items_below_item(const Glib::RefPtr<CanvasLayoutItem>& canvas_item, double y_start, double offset)
+Glib::RefPtr<CanvasLayoutItem> Canvas_PrintLayout::move_items_down(double y_start, double offset)
 {
+  //Keep track of the top-most item that needs to be moved all the way on to a new page:
+  Glib::RefPtr<CanvasLayoutItem> needs_moving_top;
+  double y_needs_moving_top = 0;
+  double needs_moving_top_height = 0;
+
   Glib::RefPtr<Goocanvas::Item> root = m_items_group;
   if(!root)
-    return;
-
-  double item_x = 0;
-  double item_y = 0;
-  canvas_item->get_xy(item_x, item_y);
-  double item_width = 0;
-  double item_height = 0;
-  canvas_item->get_width_height(item_width, item_height);
+    return needs_moving_top;
 
   double bottom_max = 0;
   
@@ -1209,13 +1207,13 @@ void Canvas_PrintLayout::move_items_below_item(const Glib::RefPtr<CanvasLayoutIt
   for(int i = 0; i < count; ++i)
   {
     Glib::RefPtr<Goocanvas::Item> child = root->get_child(i);
-    Glib::RefPtr<CanvasItemMovable> derived =
-      CanvasItemMovable::cast_to_movable(child);
+    Glib::RefPtr<CanvasLayoutItem> derived = 
+      Glib::RefPtr<CanvasLayoutItem>::cast_dynamic(child);
     if(!derived)
+    {
+      std::cout << "debug: not derived" << std::endl;
       continue;
-
-    if(derived == canvas_item)
-      continue;
+    }
 
     //Ignore items above y_start:
     double x = 0;
@@ -1228,18 +1226,29 @@ void Canvas_PrintLayout::move_items_below_item(const Glib::RefPtr<CanvasLayoutIt
     double width = 0;
     double height = 0;
     derived->get_width_height(width, height);
-    if( (x + width) < item_x)
-      continue;
+    //if( (x + width) < item_x)
+    //  continue;
 
-    if( x > (item_x + item_width))
-      continue;
+    //if( x > (item_x + item_width))
+    //  continue;
 
     //Move it down:
     y += offset;
     derived->set_xy(x, y);
+
     //Move it some more if necessary:
-    y = PrintLayoutUtils::move_fully_to_page(page_Setup, property_units(), 
-     derived);
+    //See if it should be moved down (but do that later):
+    const bool needs_moving = PrintLayoutUtils::needs_move_fully_to_page(page_Setup, property_units(), derived);
+    if(needs_moving)
+    {
+      if(!needs_moving_top || (y <= y_needs_moving_top))
+      {
+        y_needs_moving_top = y;
+
+        needs_moving_top = derived;
+        needs_moving_top_height = height;
+      }
+    }
 
     //Check where the bottom is:
     const double bottom = y + height;
@@ -1253,6 +1262,25 @@ void Canvas_PrintLayout::move_items_below_item(const Glib::RefPtr<CanvasLayoutIt
   {
     set_page_count(last_page_needed + 1);
   }
+
+  //Now move everything further, completely on to the next page
+  //and then do that again for the next page until all the pages are done:
+  if(needs_moving_top && (y_needs_moving_top > y_start))
+  {
+    std::cout << "extra move: y_needs_moving_top=" << y_needs_moving_top << std::endl;
+    const double extra_offset = 
+      PrintLayoutUtils::get_offset_to_move_fully_to_next_page(
+        page_Setup, property_units(),
+        y_needs_moving_top, needs_moving_top_height);
+    if(extra_offset)
+    {
+      needs_moving_top = move_items_down(y_needs_moving_top, extra_offset);
+    }
+    else
+      needs_moving_top.reset();
+  }
+
+  return needs_moving_top;
 }
 
 double Canvas_PrintLayout::get_page_height() const
diff --git a/glom/print_layout/canvas_print_layout.h b/glom/print_layout/canvas_print_layout.h
index 8a20b04..c5efb4b 100644
--- a/glom/print_layout/canvas_print_layout.h
+++ b/glom/print_layout/canvas_print_layout.h
@@ -91,11 +91,11 @@ public:
   Goocanvas::Bounds get_page_bounds(guint page_num) const;
 
   /** Look for any items that overlap the @a canvas_item and move them down so that the no longer overlap.
-   * @param canvas_item The item that should push items out of the way.
    * @param y_start Ignore any items whose y position is less than this.
-   * @param offset Move items down by this amount:
+   * @param offset Move items down by this amount
+   * @param result The highest item that should be moved down to the start of the next page, if any:
    */
-  void move_items_below_item(const Glib::RefPtr<CanvasLayoutItem>& canvas_item, double y_start, double offset);
+  Glib::RefPtr<CanvasLayoutItem> move_items_down(double y_start, double offset);
   
 private:
 
diff --git a/glom/print_layout/print_layout_utils.cc b/glom/print_layout/print_layout_utils.cc
index 57a17fb..a2a6d80 100644
--- a/glom/print_layout/print_layout_utils.cc
+++ b/glom/print_layout/print_layout_utils.cc
@@ -88,40 +88,49 @@ static void get_page_y_start_and_end(const Glib::RefPtr<const Gtk::PageSetup>& p
   //std::cout << G_STRFUNC << "page_number=" << page_number << ", y1=" << y1 << "y2=" << y2 << std::endl;
 }
 
-
-static double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, double y, double height)
+double get_offset_to_move_fully_to_next_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;
+    return usable_page_start - y;
   }
 
   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:
+  if((y + height) > usable_page_end) //If it is in the bottom margin:
   {
     //Move it to the start of the next page:
-    y = (current_page + 1) * page_height + top_margin + GRID_GAP;
+    const double start_next_page_y = (current_page + 1) * page_height + top_margin + GRID_GAP;
+    return start_next_page_y - y;
   }
 
-  return y;
+  return 0;
 }
 
-double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const Glib::RefPtr<CanvasItemMovable>& item)
+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 double offset = get_offset_to_move_fully_to_next_page(page_setup, units, y, height);
+  return y + offset;
+}
+
+bool needs_move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const Glib::RefPtr<const CanvasItemMovable>& item)
 {
   double x = 0;
   double y = 0;
@@ -131,11 +140,14 @@ double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup,
   double height = 0;
   item->get_width_height(width, height);
   
+  //We don't actually move it, because items would then group together 
+  //at the top of pages.
+  //Instead, the caller will discover an offset to apply to all items:
   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;
+    return true;
+
+  return false;
 }
 
 /*
diff --git a/glom/print_layout/print_layout_utils.h b/glom/print_layout/print_layout_utils.h
index be2101e..e9ea15b 100644
--- a/glom/print_layout/print_layout_utils.h
+++ b/glom/print_layout/print_layout_utils.h
@@ -53,12 +53,14 @@ double get_page_height(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk
  */
 guint get_page_for_y(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, double y);
 
-/** Move the item to the start of a page, past the top margin,
- * if it is currently in the bottom margin of a page, or in the top margin of a page.
+/** See if the item needs to move to the start of a page, past the top margin,
+ * or if it is currently in the bottom margin of a page, or in the top margin of a page.
  *
- * @result The new y position of the item.
+ * @result Whether the item needs to be moved.
  */
-double move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const Glib::RefPtr<CanvasItemMovable>& item);
+bool needs_move_fully_to_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, const Glib::RefPtr<const CanvasItemMovable>& item);
+
+double get_offset_to_move_fully_to_next_page(const Glib::RefPtr<const Gtk::PageSetup>& page_setup, Gtk::Unit units, double y, double height);
 
 } //namespace PrintLayoutUtils
 



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