[glom] Print Layout: Add a Show Outlines menu item



commit 09e8ee35c582e7ba4391a3e2bfd3ac3e20c53e7d
Author: Murray Cumming <murrayc murrayc com>
Date:   Mon Aug 8 19:26:58 2011 +0200

    Print Layout: Add a Show Outlines menu item
    
    * glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]
    View menu: Add Show Outlines, with a handler, to show the extents of
    the items.
    * glom/utility_widgets/canvas/canvas_group_resizable.[h|cc]:
    Added a new group with lines, in a thinner fainter gray, to indicate
    the outline. Added set_outline_visible() to show it.
    Move it whenever the child item moves, like the manipulator lines.
    * glom/print_layout/canvas_print_layout.[h|cc]:
    Added set_outlines_visibility() to call this on all items.
    Store the value as a bool so we can use it again in
    add_canvas_layout_item().

 ChangeLog                                          |   16 +++
 .../print_layouts/window_print_layout_edit.cc      |   10 ++
 .../print_layouts/window_print_layout_edit.h       |    3 +-
 glom/print_layout/canvas_print_layout.cc           |   28 +++++-
 glom/print_layout/canvas_print_layout.h            |    4 +
 .../canvas/canvas_group_resizable.cc               |  117 ++++++++++++++++++--
 .../canvas/canvas_group_resizable.h                |   20 +++-
 7 files changed, 185 insertions(+), 13 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 345fc3f..e77a788 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2011-08-08  Murray Cumming  <murrayc murrayc com>
 
+	Print Layout: Add a Show Outlines menu item
+
+	* glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]
+	View menu: Add Show Outlines, with a handler, to show the extents of 
+	the items.
+	* glom/utility_widgets/canvas/canvas_group_resizable.[h|cc]:
+	Added a new group with lines, in a thinner fainter gray, to indicate 
+	the outline. Added set_outline_visible() to show it.
+	Move it whenever the child item moves, like the manipulator lines.
+	* glom/print_layout/canvas_print_layout.[h|cc]:
+	Added set_outlines_visibility() to call this on all items.
+	Store the value as a bool so we can use it again in 
+	add_canvas_layout_item().
+
+2011-08-08  Murray Cumming  <murrayc murrayc com>
+
 	Print Layout: Allow moving of multiple items via x and y numbers.
 
 	* glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]:
diff --git a/glom/mode_design/print_layouts/window_print_layout_edit.cc b/glom/mode_design/print_layouts/window_print_layout_edit.cc
index 4fe934d..195dd67 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.cc
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.cc
@@ -200,6 +200,8 @@ void Window_PrintLayout_Edit::init_menu()
   m_action_group->add(m_action_showgrid, sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_view_show_grid));
   m_action_showrules = Gtk::ToggleAction::create("Action_Menu_View_ShowRules", _("Show Rules"));
   m_action_group->add(m_action_showrules, sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_view_show_rules));
+  m_action_showoutlines = Gtk::ToggleAction::create("Action_Menu_View_ShowOutlines", _("Show Outlines"));
+  m_action_group->add(m_action_showoutlines, sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_view_show_outlines));
 
   Gtk::RadioAction::Group group_zoom;
   m_action_zoom_fit_page_width = Gtk::RadioAction::create(group_zoom, "Action_Menu_View_ZoomFitPageWidth", _("Fit Page _Width"));
@@ -247,6 +249,7 @@ void Window_PrintLayout_Edit::init_menu()
     "      <menu action='Menu_View'>"
     "        <menuitem action='Action_Menu_View_ShowGrid' />"
     "        <menuitem action='Action_Menu_View_ShowRules' />"
+    "        <menuitem action='Action_Menu_View_ShowOutlines' />"
     "        <separator />"
     "        <menuitem action='Action_Menu_View_ZoomFitPageWidth' />"
     "        <menuitem action='Action_Menu_View_Zoom200' />"
@@ -853,6 +856,13 @@ void Window_PrintLayout_Edit::on_menu_view_show_rules()
   //TODO:
 }
 
+
+void Window_PrintLayout_Edit::on_menu_view_show_outlines()
+{
+  m_canvas.set_outlines_visibility(
+    m_action_showoutlines->get_active());
+}
+
 void Window_PrintLayout_Edit::on_menu_view_zoom(guint percent)
 {
   m_canvas.set_zoom_percent(percent);
diff --git a/glom/mode_design/print_layouts/window_print_layout_edit.h b/glom/mode_design/print_layouts/window_print_layout_edit.h
index 2c65ea3..895a786 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.h
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.h
@@ -71,6 +71,7 @@ private:
   void on_menu_insert_line_vertical();
   void on_menu_view_show_grid();
   void on_menu_view_show_rules();
+  void on_menu_view_show_outlines();
   void on_menu_view_zoom(guint percent);
   void on_menu_view_fitpagewidth();
 
@@ -167,7 +168,7 @@ private:
   //Main menu:
   Glib::RefPtr<Gtk::ActionGroup> m_action_group;
   Glib::RefPtr<Gtk::UIManager> m_uimanager;
-  Glib::RefPtr<Gtk::ToggleAction> m_action_showgrid, m_action_showrules;
+  Glib::RefPtr<Gtk::ToggleAction> m_action_showgrid, m_action_showrules, m_action_showoutlines;
   Glib::RefPtr<Gtk::ToggleAction> m_action_zoom_fit_page_width;
 
   //Edit menu:
diff --git a/glom/print_layout/canvas_print_layout.cc b/glom/print_layout/canvas_print_layout.cc
index d095f23..c12bcc5 100644
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@ -47,7 +47,8 @@ static bool on_group_button_press_event(const Glib::RefPtr<Goocanvas::Item>& tar
 
 Canvas_PrintLayout::Canvas_PrintLayout()
 : m_modified(false),
-  m_dialog_format(0)
+  m_dialog_format(0),
+  m_outline_visibility(false)
 {
   #ifndef GLOM_ENABLE_CLIENT_ONLY
   setup_context_menu();
@@ -168,6 +169,8 @@ void Canvas_PrintLayout::add_canvas_layout_item(const Glib::RefPtr<CanvasLayoutI
       sigc::mem_fun(*this, &Canvas_PrintLayout::on_item_show_context_menu),
       item) );
 #endif //GLOM_ENABLE_CLIENT_ONLY
+
+   item->set_outline_visible(m_outline_visibility);
 }
 
 void Canvas_PrintLayout::remove_canvas_layout_item(const Glib::RefPtr<CanvasLayoutItem>& item)
@@ -882,4 +885,27 @@ Canvas_PrintLayout::type_vec_items Canvas_PrintLayout::get_selected_items()
   return result;
 }
 
+void Canvas_PrintLayout::set_outlines_visibility(bool visible)
+{
+  //Remember this so we can apply it to items added later:
+  m_outline_visibility = visible;
+
+  //TODO: Do this recursively.
+  Glib::RefPtr<Goocanvas::Item> root = m_items_group;
+  if(!root)
+    return;
+
+  const int count = root->get_n_children();
+  for(int i = 0; i < count; ++i)
+  {
+    Glib::RefPtr<Goocanvas::Item> child = root->get_child(i);
+    Glib::RefPtr<CanvasLayoutItem> derived =
+      Glib::RefPtr<CanvasLayoutItem>::cast_dynamic(child);
+    if(!derived)
+      continue;
+
+    derived->set_outline_visible(visible);
+  }
+}
+
 } //namespace Glom
diff --git a/glom/print_layout/canvas_print_layout.h b/glom/print_layout/canvas_print_layout.h
index f50ffd8..6723b60 100644
--- a/glom/print_layout/canvas_print_layout.h
+++ b/glom/print_layout/canvas_print_layout.h
@@ -65,6 +65,8 @@ public:
 
   virtual void set_grid_gap(double gap = 20.0);
 
+  void set_outlines_visibility(bool visible = true);
+
   /** Get any items that have get_selected()==true.
    */
   virtual type_vec_items get_selected_items();
@@ -123,6 +125,8 @@ private:
   Glib::RefPtr<Gtk::PageSetup> m_page_setup;
 
   Dialog_TextFormatting* m_dialog_format;
+
+  bool m_outline_visibility;
 };
 
 } //namespace Glom
diff --git a/glom/utility_widgets/canvas/canvas_group_resizable.cc b/glom/utility_widgets/canvas/canvas_group_resizable.cc
index 22e4297..27f7755 100644
--- a/glom/utility_widgets/canvas/canvas_group_resizable.cc
+++ b/glom/utility_widgets/canvas/canvas_group_resizable.cc
@@ -31,8 +31,10 @@ namespace Glom
 
 static const double manipulator_corner_size = 2;
 static const gchar* manipulator_corner_fill_color = "black";
-static const double manipulator_stroke_width = 1.0; //mm (assuming that the canvas uses mm.
+static const double manipulator_stroke_width = 1.0f; //mm (assuming that the canvas uses mm.
 static const gchar* manipulator_stroke_color = "black";
+static const double outline_stroke_width = 0.5f; //mm (assuming that the canvas uses mm.
+static const gchar* outline_stroke_color = "gray";
 
 CanvasGroupResizable::CanvasGroupResizable()
 : m_in_manipulator(false),
@@ -158,6 +160,47 @@ void CanvasGroupResizable::create_line_manipulators()
   manipulator_connect_signals(m_manipulator_end, MANIPULATOR_END);
 }
 
+Glib::RefPtr<CanvasLineMovable> CanvasGroupResizable::create_outline_line(double x1, double y1, double x2, double y2)
+{
+  Glib::RefPtr<CanvasLineMovable> line = Glom::CanvasLineMovable::create();
+  line->property_line_width() = outline_stroke_width;
+  line->property_stroke_color() = outline_stroke_color;
+  m_group_outline->add_child(line);
+  set_edge_points(line, x1, y1, x2, y2);
+  return line;
+}
+
+void CanvasGroupResizable::create_outline_group()
+{
+  //Add something to indicate when the item is selected:
+  if(m_group_outline)
+    m_group_outline->remove();
+  m_group_outline = Goocanvas::Group::create();
+  add_child(m_group_outline);
+
+  double x1 = 0;
+  double y1 = 0;
+  get_xy(x1, y1);
+
+  double child_width = 0;
+  double child_height = 0;
+  get_width_height(child_width, child_height);
+
+  const double x2 = x1 + child_width;
+  const double y2 = y1 + child_height;
+
+  m_outline_top = create_outline_line(x1, y1, x2, y1);
+  m_outline_bottom = create_outline_line(x1, y2, x2, y2);
+  m_outline_left = create_outline_line(x1, y1, x1, y2);
+  m_outline_right = create_outline_line(x2, y1, x2, y2);
+}
+
+void CanvasGroupResizable::set_outline_visible(bool visible)
+{
+  m_group_outline->property_visibility() = 
+    (visible ? Goocanvas::ITEM_VISIBLE : Goocanvas::ITEM_INVISIBLE);
+}
+
 CanvasGroupResizable::~CanvasGroupResizable()
 {
 }
@@ -167,6 +210,12 @@ Glib::RefPtr<CanvasGroupResizable> CanvasGroupResizable::create()
   return Glib::RefPtr<CanvasGroupResizable>(new CanvasGroupResizable());
 }
 
+void CanvasGroupResizable::position_extras()
+{
+  position_manipulators();
+  position_outline();
+}
+
 void CanvasGroupResizable::position_manipulators()
 {
   if(get_is_line())
@@ -190,7 +239,7 @@ void CanvasGroupResizable::position_rect_manipulators()
 
   double child_x = 0;
   double child_y = 0;
-  get_xy(child_x, child_y);
+  get_xy(child_x, child_y); //TODO: Remove duplicate get_xy() call?
   //std::cout << "debug: " << G_STRFUNC << ": child x=" << child_x << std::endl;
 
   double child_width = 0;
@@ -262,6 +311,51 @@ void CanvasGroupResizable::position_line_manipulators()
   m_group_corner_manipulators->raise(line);
 }
 
+void CanvasGroupResizable::position_outline()
+{
+  if(!m_rect)
+    return;
+
+  //Note that this only works after the child has been added to the canvas:
+  //Goocanvas::Bounds bounds;
+  //m_child->get_bounds(bounds);
+ 
+  double x1 = 0;
+  double y1 = 0;
+  get_xy(x1, y1);
+
+  double child_width = 0;
+  double child_height = 0;
+  get_width_height(child_width, child_height);
+  //std::cout << "debug: " << G_STRFUNC << ": child width=" << child_width << std::endl;
+
+  const double x2 = x1 + child_width;
+  const double y2 = y1 + child_height;
+
+  Glib::RefPtr<Goocanvas::Item> item = CanvasItemMovable::cast_to_item(m_child);
+
+  set_edge_points(m_outline_top, x1, y1, x2, y1);
+  set_edge_points(m_outline_bottom, x1, y2, x2, y2);
+  set_edge_points(m_outline_left, x1, y1, x1, y2);
+  set_edge_points(m_outline_right, x2, y1, x2, y2);
+
+  /*
+  //Make sure that the bounds rect is below the item,
+  //and the manipulators are above the item (and above the rect):
+  if(item)
+  {
+    m_group_edge_manipulators->raise(item);
+    m_group_corner_manipulators->raise(item);
+    m_rect->lower(item);
+  }
+  else
+  {
+    m_group_edge_manipulators->raise(m_rect);
+    m_group_corner_manipulators->raise(m_rect);
+  }
+  */
+}
+
 void CanvasGroupResizable::set_child(const Glib::RefPtr<CanvasItemMovable>& child)
 {
   //Remove the previous child, if any:
@@ -304,14 +398,17 @@ void CanvasGroupResizable::set_child(const Glib::RefPtr<CanvasItemMovable>& chil
 
   create_manipulators(); //Potentially changing the type of manipulators used, if the item is of a different type.
 
+  create_outline_group();
+
   //Set the child's position to match this parent resizable's position, if any was set:
   //(Note that the resizable should have its position set to that of the child, 
   //if that is the position that is wanted. 
   set_xy(x, y);
   set_width_height(width, height);
 
-  position_manipulators();
+  position_extras();
   set_manipulators_visibility(Goocanvas::ITEM_INVISIBLE);
+  set_outline_visible(false);
 }
 
 Glib::RefPtr<CanvasItemMovable> CanvasGroupResizable::get_child()
@@ -325,7 +422,7 @@ Glib::RefPtr<const CanvasItemMovable> CanvasGroupResizable::get_child() const
   return m_child;
 }
 
-void CanvasGroupResizable::manipulator_connect_signals(const Glib::RefPtr<Goocanvas::Item> manipulator, Manipulators manipulator_id)
+void CanvasGroupResizable::manipulator_connect_signals(const Glib::RefPtr<Goocanvas::Item>& manipulator, Manipulators manipulator_id)
 {
   //Respond when the corner rectangles move (they implement their own dragging):
 
@@ -479,7 +576,7 @@ void CanvasGroupResizable::on_manipulator_corner_moved(const Glib::RefPtr<Canvas
       break;
   }
 
-  position_manipulators();
+  position_extras();
   m_signal_resized.emit();
 }
 
@@ -516,7 +613,7 @@ void CanvasGroupResizable::on_manipulator_line_end_moved(const Glib::RefPtr<Canv
   points.set_coordinate(point_index, manipulator_x + half_size, manipulator_y + half_size);
   line->property_points() = points; //TODO: Add a way to do this without getting and setting the points property.
 
-  position_manipulators();
+  position_extras();
 }
 
 bool CanvasGroupResizable::on_manipulator_enter_notify_event(const Glib::RefPtr<Goocanvas::Item>& /* target */, GdkEventCrossing* /* event */)
@@ -602,7 +699,7 @@ void CanvasGroupResizable::on_manipulator_edge_moved(const Glib::RefPtr<CanvasIt
       break;
   }
 
-  position_manipulators();
+  position_extras();
   
   m_signal_resized.emit();
 }
@@ -619,7 +716,7 @@ bool CanvasGroupResizable::on_child_motion_notify_event(const Glib::RefPtr<Gooca
 
   const bool result = CanvasItemMovable::on_motion_notify_event(target, event);
   
-  position_manipulators();
+  position_extras();
 
   return result;
 }
@@ -756,7 +853,7 @@ void CanvasGroupResizable::set_xy(double x, double y)
   m_x = x;
   m_y = y;
 
-  position_manipulators();
+  position_extras();
 }
 
 void CanvasGroupResizable::get_width_height(double& width, double& height) const
@@ -788,7 +885,7 @@ void CanvasGroupResizable::set_width_height(double width, double height)
   m_width = width;
   m_height = height;
 
-  position_manipulators();
+  position_extras();
 }
 
 void CanvasGroupResizable::snap_position(double& x, double& y) const
diff --git a/glom/utility_widgets/canvas/canvas_group_resizable.h b/glom/utility_widgets/canvas/canvas_group_resizable.h
index 422bd8b..fa96971 100644
--- a/glom/utility_widgets/canvas/canvas_group_resizable.h
+++ b/glom/utility_widgets/canvas/canvas_group_resizable.h
@@ -63,6 +63,8 @@ public:
 
   virtual void snap_position(double& x, double& y) const;
 
+  void set_outline_visible(bool visible = true);
+
   typedef sigc::signal<void> type_signal_resized;
 
   /// This signal is emitted when the canvas item is resized by the user.
@@ -120,18 +122,29 @@ private:
   void create_rect_manipulators();
   void create_line_manipulators();
 
-  void manipulator_connect_signals(const Glib::RefPtr<Goocanvas::Item> manipulator, Manipulators manipulator_id);
+  void create_outline_group();
+  Glib::RefPtr<CanvasLineMovable> create_outline_line(double x1, double y1, double x2, double y2);
+
+
+  void manipulator_connect_signals(const Glib::RefPtr<Goocanvas::Item>& manipulator, Manipulators manipulator_id);
   void position_manipulators();
   void position_rect_manipulators();
   void position_line_manipulators();
   void set_manipulators_visibility(Goocanvas::ItemVisibility visibility);
 
+  void position_outline();
+
+  /** Make sure that the outline and manipulators are correctly placed and sized.
+   */
+  void position_extras();
+
   void on_manipulator_corner_moved(const Glib::RefPtr<CanvasItemMovable>& item, double x_offset, double y_offset, Manipulators manipulator_id);
   void on_manipulator_edge_moved(const Glib::RefPtr<CanvasItemMovable>& item, double x_offset, double y_offset, Manipulators manipulator_id);
   void on_manipulator_line_end_moved(const Glib::RefPtr<CanvasItemMovable>& item, double x_offset, double y_offset, Manipulators manipulator_id);
   bool on_manipulator_enter_notify_event(const Glib::RefPtr<Goocanvas::Item>& target, GdkEventCrossing* event);
   bool on_manipulator_leave_notify_event(const Glib::RefPtr<Goocanvas::Item>& target, GdkEventCrossing* event);
 
+
   bool get_is_line() const;
 
   //bool on_manipulator_button_press_event(const Glib::RefPtr<Goocanvas::Item>& target, GdkEventButton* event, Manipulators manipulator);
@@ -155,6 +168,11 @@ private:
   //Manipulators for a line:
   Glib::RefPtr<CanvasRectMovable> m_manipulator_start, m_manipulator_end;
 
+  //These are visible to indicate the item's dimensions:
+  Glib::RefPtr<Goocanvas::Group> m_group_outline;
+  Glib::RefPtr<CanvasLineMovable> m_outline_top, m_outline_bottom, m_outline_left, m_outline_right;
+
+
   bool m_in_manipulator; //Whether the cursor is in a manipulator.
 
   //These are used only before there is a child.



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