[glom] Print Layout: Implement cut/copy/paste/delete.



commit 54cc4d0bdd2496f99fee15c6dd0a1627e8e1ce68
Author: Murray Cumming <murrayc murrayc com>
Date:   Sat Aug 6 19:08:26 2011 +0200

    Print Layout: Implement cut/copy/paste/delete.
    
    * glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]:
    Implement the edit menu, enabling/disabling the menu items based on
    whether something has been selected or previously copied.
    * glom/utility_widgets/canvas/canvas_editable.[h|cc]: Added
    get_selected_items() here, making it virtual. The override in
    Canvas_PrintLayout is the only real implementation so far.
    Added remove_item().
    remove_all_items(): Emit signal_selection_changed if something
    was selected.
    * glom/print_layout/canvas_print_layout.[h|cc]:
    Added remove_canvas_layout_item().
    Removed update_layout_position_from_canvas(), putting it in
    Canvas_LayoutItem instead.
    * glom/print_layout/canvas_layout_item.[h|cc]:
    Added update_layout_position_from_canvas().

 ChangeLog                                          |   20 ++++
 .../print_layouts/window_print_layout_edit.cc      |   97 +++++++++++++++++---
 .../print_layouts/window_print_layout_edit.h       |   13 +++
 glom/print_layout/canvas_layout_item.cc            |   19 ++++
 glom/print_layout/canvas_layout_item.h             |    4 +
 glom/print_layout/canvas_print_layout.cc           |   44 +++------
 glom/print_layout/canvas_print_layout.h            |    9 +-
 glom/utility_widgets/canvas/canvas_editable.cc     |   35 +++++++-
 glom/utility_widgets/canvas/canvas_editable.h      |   11 ++
 9 files changed, 206 insertions(+), 46 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0a1c776..1e813c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2011-08-06  Murray Cumming  <murrayc murrayc com>
 
+	Print Layout: Implement cut/copy/paste/delete.
+
+	* glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]:
+	Implement the edit menu, enabling/disabling the menu items based on 
+	whether something has been selected or previously copied.
+	* glom/utility_widgets/canvas/canvas_editable.[h|cc]: Added 
+	get_selected_items() here, making it virtual. The override in 
+	Canvas_PrintLayout is the only real implementation so far.
+	Added remove_item().
+	remove_all_items(): Emit signal_selection_changed if something 
+	was selected.
+	* glom/print_layout/canvas_print_layout.[h|cc]:
+	Added remove_canvas_layout_item().
+	Removed update_layout_position_from_canvas(), putting it in 
+	Canvas_LayoutItem instead.
+	* glom/print_layout/canvas_layout_item.[h|cc]:
+	Added update_layout_position_from_canvas().
+
+2011-08-06  Murray Cumming  <murrayc murrayc com>
+
 	CanvasPrintLayout: Remove unused method overload.
 
 	* glom/print_layout/canvas_print_layout.[h|cc]: get_selected_items():
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 66dd309..9971cd3 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.cc
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.cc
@@ -147,7 +147,7 @@ Window_PrintLayout_Edit::Window_PrintLayout_Edit(BaseObjectType* cobject, const
 
   m_canvas.signal_selection_changed().connect(
     sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_canvas_selection_changed));
-  on_canvas_selection_changed(); //Disable relevant widgets by default.
+  on_canvas_selection_changed(); //Disable relevant widgets or actions by default.
   
   show_all_children();
 }
@@ -160,11 +160,25 @@ void Window_PrintLayout_Edit::init_menu()
   m_action_group->add(Gtk::Action::create("Action_Menu_File_PageSetup", _("Page _Setup")),
     sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_file_page_setup));
 
+
   m_action_group->add(Gtk::Action::create("Menu_Edit", Gtk::Stock::EDIT));
-  m_action_group->add(Gtk::Action::create("Action_Menu_Edit_Cut", Gtk::Stock::CUT));
-  m_action_group->add(Gtk::Action::create("Action_Menu_Edit_Copy", Gtk::Stock::COPY));
-  m_action_group->add(Gtk::Action::create("Action_Menu_Edit_Paste", Gtk::Stock::PASTE));
-  m_action_group->add(Gtk::Action::create("Action_Menu_Edit_Delete", Gtk::Stock::DELETE));
+
+  m_action_edit_cut = Gtk::Action::create("Action_Menu_Edit_Cut", Gtk::Stock::CUT);
+  m_action_group->add(m_action_edit_cut,
+    sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_edit_cut) );
+
+  m_action_edit_copy = Gtk::Action::create("Action_Menu_Edit_Copy", Gtk::Stock::COPY);
+  m_action_group->add(m_action_edit_copy,
+    sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_edit_copy) );
+  
+  m_action_edit_paste = Gtk::Action::create("Action_Menu_Edit_Paste", Gtk::Stock::PASTE);
+  m_action_group->add(m_action_edit_paste,
+    sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_edit_paste) );
+  m_action_edit_paste->set_sensitive(false); //This is enable when something is copied or cut.
+
+  m_action_edit_delete = Gtk::Action::create("Action_Menu_Edit_Delete", Gtk::Stock::DELETE);
+  m_action_group->add(m_action_edit_delete,
+    sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_menu_edit_delete) );
 
   m_action_group->add(Gtk::Action::create("Menu_Insert", _("_Insert")));
   m_action_group->add(Gtk::Action::create("Action_Menu_Insert_Field", _("Insert _Field")),
@@ -881,6 +895,56 @@ void Window_PrintLayout_Edit::on_menu_file_page_setup()
   set_ruler_sizes();
 }
 
+void Window_PrintLayout_Edit::on_menu_edit_cut()
+{
+  on_menu_edit_copy();
+  on_menu_edit_delete();
+}
+
+void Window_PrintLayout_Edit::on_menu_edit_copy()
+{
+  if(!m_layout_item_selected)
+    return;
+
+  m_layout_item_selected->update_layout_position_from_canvas();
+  m_layout_item_to_paste = 
+    glom_sharedptr_clone(m_layout_item_selected->get_layout_item());
+
+  m_action_edit_paste->set_sensitive();
+}
+
+void Window_PrintLayout_Edit::on_menu_edit_paste()
+{
+  if(!m_layout_item_to_paste)
+    return;
+
+  //TODO: Add x,y offset and add.
+  double x = 0;
+  double y = 0;
+  double width = 0;
+  double height = 0;
+  m_layout_item_to_paste->get_print_layout_position(
+    x, y, width, height);
+
+  const double offset = 5;
+  x += offset;
+  y += offset;
+  m_layout_item_to_paste->set_print_layout_position(x, y, width, height);
+
+  Glib::RefPtr<CanvasLayoutItem> item = 
+    CanvasLayoutItem::create(m_layout_item_to_paste);
+  m_canvas.add_canvas_layout_item(item);
+}
+
+void Window_PrintLayout_Edit::on_menu_edit_delete()
+{
+  if(!m_layout_item_selected)
+     return;
+
+  m_canvas.remove_canvas_layout_item(m_layout_item_selected);
+  m_layout_item_selected.reset();
+}
+
 static void spinbutton_set_max(Gtk::SpinButton& spinbutton, double max)
 {
   spinbutton.set_range(0, max);
@@ -949,7 +1013,7 @@ void Window_PrintLayout_Edit::on_canvas_selection_changed()
   for(Canvas_PrintLayout::type_vec_items::const_iterator iter = items.begin();
     iter != items.end(); ++iter)
   {
-    Glib::RefPtr<CanvasLayoutItem> item = *iter;
+    Glib::RefPtr<CanvasLayoutItem> item = Glib::RefPtr<CanvasLayoutItem>::cast_dynamic(*iter);
     if(!item)
       continue;
 
@@ -977,6 +1041,12 @@ void Window_PrintLayout_Edit::on_canvas_selection_changed()
     first = false;
   }
 
+  const bool one_selected = (items.size() == 1);
+  if(one_selected)
+    m_layout_item_selected = Glib::RefPtr<CanvasLayoutItem>::cast_dynamic(items[0]);
+  else
+    m_layout_item_selected.reset();
+
   const double width = x2 - x;
   const double height = y2 - y;
 
@@ -988,13 +1058,16 @@ void Window_PrintLayout_Edit::on_canvas_selection_changed()
   //Disable the spinbuttons if there are no items selected,
   //or if there are more than 1.
   //TODO: Let the user resize groups of items.
-  const bool enable = (items.size() == 1);
-  m_box_item_position->set_sensitive(enable);
+  m_box_item_position->set_sensitive(one_selected);
 
-  if(enable)
-    m_layout_item_selected = items[0];
-  else
-    m_layout_item_selected.reset();
+  if(m_action_edit_cut)
+    m_action_edit_cut->set_sensitive(one_selected);
+
+  if(m_action_edit_copy)
+    m_action_edit_copy->set_sensitive(one_selected);
+
+  if(m_action_edit_delete)
+    m_action_edit_delete->set_sensitive(one_selected);
 }
 
 void Window_PrintLayout_Edit::on_spinbutton_x()
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 d5fad86..21b22dd 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.h
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.h
@@ -74,6 +74,12 @@ private:
   void on_menu_view_zoom(guint percent);
   void on_menu_view_fitpagewidth();
 
+  void on_menu_edit_cut();
+  void on_menu_edit_copy();
+  void on_menu_edit_paste();
+  void on_menu_edit_delete();
+
+
   void on_canvas_show_context_menu(guint button, guint32 activate_time);
   void on_context_menu_insert_field();
   void on_context_menu_insert_text();
@@ -144,6 +150,9 @@ private:
   //to avoid repeatedly requesting it:
   Glib::RefPtr<CanvasLayoutItem> m_layout_item_selected;
 
+  //A copied item to be pasted later:
+  sharedptr<LayoutItem> m_layout_item_to_paste;
+
   GimpRuler* m_vruler;
   GimpRuler* m_hruler;
 
@@ -153,6 +162,10 @@ private:
   Glib::RefPtr<Gtk::ToggleAction> m_action_showgrid, m_action_showrules;
   Glib::RefPtr<Gtk::ToggleAction> m_action_zoom_fit_page_width;
 
+  //Edit menu:
+  Glib::RefPtr<Gtk::Action> m_action_edit_cut, m_action_edit_copy, 
+    m_action_edit_paste, m_action_edit_delete;
+
   //Toolbar:
   Gtk::HandleBox* m_palette_handle_box; //TODO: The toolbar is already a HandleBox.
   std::vector<Gtk::TargetEntry> m_drag_targets;
diff --git a/glom/print_layout/canvas_layout_item.cc b/glom/print_layout/canvas_layout_item.cc
index de2893b..709fc34 100644
--- a/glom/print_layout/canvas_layout_item.cc
+++ b/glom/print_layout/canvas_layout_item.cc
@@ -447,4 +447,23 @@ void CanvasLayoutItem::remove_empty_indicators()
   }
 }
 
+void CanvasLayoutItem::update_layout_position_from_canvas()
+{
+  sharedptr<LayoutItem> layout_item = get_layout_item();
+  if(!layout_item)
+    return;
+
+  //Get the actual position:
+  double x = 0;
+  double y = 0;
+  get_xy(x, y);
+  //std::cout << "debug: " << G_STRFUNC << ": x=" << x << std::endl;
+
+  double width = 0;
+  double height = 0;
+  get_width_height(width, height);
+
+  layout_item->set_print_layout_position(x, y, width, height);
+}
+
 } //namespace Glom
diff --git a/glom/print_layout/canvas_layout_item.h b/glom/print_layout/canvas_layout_item.h
index 47cc4ad..954243b 100644
--- a/glom/print_layout/canvas_layout_item.h
+++ b/glom/print_layout/canvas_layout_item.h
@@ -63,6 +63,10 @@ public:
 
   static int get_rows_count_for_portal(const sharedptr<const LayoutItem_Portal>& portal, double& row_height);
 
+  /** Make sure that the LayoutItem has the same position info as the CanvasItem that represents it.
+   */
+  void update_layout_position_from_canvas();
+
 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);
diff --git a/glom/print_layout/canvas_print_layout.cc b/glom/print_layout/canvas_print_layout.cc
index 91b27fc..6dcb723 100644
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@ -153,7 +153,7 @@ void Canvas_PrintLayout::add_layout_group_children(const sharedptr<LayoutGroup>&
   m_modified = true;
 }
 
-void Canvas_PrintLayout::add_canvas_layout_item(const Glib::RefPtr<CanvasLayoutItem> item)
+void Canvas_PrintLayout::add_canvas_layout_item(const Glib::RefPtr<CanvasLayoutItem> item) //TODO: Pass by ref.
 {
   if(!item)
     return;
@@ -169,7 +169,14 @@ 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
+}
+
+void Canvas_PrintLayout::remove_canvas_layout_item(const Glib::RefPtr<CanvasLayoutItem>& item)
+{
+  if(!item)
+    return;
 
+  CanvasEditable::remove_item(item, m_items_group);
 }
 
 void Canvas_PrintLayout::add_layout_group(const sharedptr<LayoutGroup>& group, bool is_top_level)
@@ -211,11 +218,9 @@ void Canvas_PrintLayout::fill_layout_group(const sharedptr<LayoutGroup>& group)
       if((width != 0)) //Allow height to be 0, because text items currently have no height. TODO: && (height != 0)) //Avoid bogus items.
       {
       */
-        sharedptr<LayoutItem> layout_item = canvas_item->get_layout_item();
-        //std::cout << "DEBUG: saving layout_item type=" << layout_item->get_part_type_name() << std::endl;
-        update_layout_position_from_canvas(layout_item, canvas_item);
+        canvas_item->update_layout_position_from_canvas();
 
-        group->add_item(layout_item);
+        group->add_item(canvas_item->get_layout_item());
       //}
     }
 
@@ -318,10 +323,11 @@ void Canvas_PrintLayout::on_context_menu_edit()
 {
   Gtk::Window* parent = dynamic_cast<Gtk::Window*>(get_toplevel());
 
-  sharedptr<LayoutItem> layout_item = m_context_item->get_layout_item();
-  update_layout_position_from_canvas(layout_item, m_context_item);
+  m_context_item->update_layout_position_from_canvas();
 
-  sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
+  sharedptr<LayoutItem> layout_item = m_context_item->get_layout_item();
+  sharedptr<LayoutItem_Field> field = 
+    sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
   if(field)
   {
     sharedptr<LayoutItem_Field> field_chosen = offer_field_list_select_one_field(field, m_table_name, parent);
@@ -366,9 +372,9 @@ void Canvas_PrintLayout::on_context_menu_formatting()
   if(!m_context_item)
     return;
 
-  sharedptr<LayoutItem> layout_item = m_context_item->get_layout_item();
-  update_layout_position_from_canvas(layout_item, m_context_item);
+  m_context_item->update_layout_position_from_canvas();
 
+  sharedptr<LayoutItem> layout_item = m_context_item->get_layout_item();
   sharedptr<LayoutItem_Field> layout_item_field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
   sharedptr<LayoutItem_Text> layout_item_text = sharedptr<LayoutItem_Text>::cast_dynamic(layout_item);
   if(!layout_item_field && !layout_item_text)
@@ -434,24 +440,6 @@ void Canvas_PrintLayout::on_dialog_format_hide()
 
 #endif //GLOM_ENABLE_CLIENT_ONLY
 
-
-void Canvas_PrintLayout::update_layout_position_from_canvas(const sharedptr<LayoutItem> layout_item, const Glib::RefPtr<const CanvasLayoutItem>& canvas_item)
-{
-  if(!layout_item || !canvas_item)
-    return;
-
-  //Get the actual position:
-  double x = 0;
-  double y = 0;
-  canvas_item->get_xy(x, y);
-  //std::cout << "debug: " << G_STRFUNC << ": x=" << x << std::endl;
-
-  double width = 0;
-  double height = 0;
-  canvas_item->get_width_height(width, height);
-  layout_item->set_print_layout_position(x, y, width, height);
-}
-
 Glib::RefPtr<Goocanvas::Polyline> Canvas_PrintLayout::create_margin_line(double x1, double y1, double x2, double y2)
 {
   Glib::RefPtr<Goocanvas::Polyline> line =
diff --git a/glom/print_layout/canvas_print_layout.h b/glom/print_layout/canvas_print_layout.h
index b3194dc..5009f77 100644
--- a/glom/print_layout/canvas_print_layout.h
+++ b/glom/print_layout/canvas_print_layout.h
@@ -56,18 +56,18 @@ public:
    */
   void hide_page_bounds();
 
-  //Override:
+  //Override: TODO: Is it really?
   void add_canvas_layout_item(const Glib::RefPtr<CanvasLayoutItem> item);
 
+  void remove_canvas_layout_item(const Glib::RefPtr<CanvasLayoutItem>& item);
+
   void fill_with_data(const FoundSet& found_set);
 
   virtual void set_grid_gap(double gap = 20.0);
 
-  typedef std::vector< Glib::RefPtr<CanvasLayoutItem> > type_vec_items;
-
   /** Get any items that have get_selected()==true.
    */
-  type_vec_items get_selected_items();
+  virtual type_vec_items get_selected_items();
   
 private:
 
@@ -100,7 +100,6 @@ private:
 #endif
 
   Glib::RefPtr<Goocanvas::Polyline> create_margin_line(double x1, double y1, double x2, double y2);
-  static void update_layout_position_from_canvas(const sharedptr<LayoutItem> layout_item, const Glib::RefPtr<const CanvasLayoutItem>& canvas_item);
 
   Glib::ustring m_table_name;
   bool m_modified; //TODO: Actually check this?
diff --git a/glom/utility_widgets/canvas/canvas_editable.cc b/glom/utility_widgets/canvas/canvas_editable.cc
index 2272bc9..465facb 100644
--- a/glom/utility_widgets/canvas/canvas_editable.cc
+++ b/glom/utility_widgets/canvas/canvas_editable.cc
@@ -99,17 +99,44 @@ void CanvasEditable::add_item(const Glib::RefPtr<Goocanvas::Item>& item, const G
   }
 }
 
+void CanvasEditable::remove_item(const Glib::RefPtr<Goocanvas::Item>& item , const Glib::RefPtr<Goocanvas::Group>& group)
+{
+  if(!group)
+   return;
+
+  //TODO: Remove resizable=true items via their parent item.
+  item->remove();
+
+  Glib::RefPtr<CanvasItemMovable> movable = Glib::RefPtr<CanvasItemMovable>::cast_dynamic(item);
+  if(movable && movable->get_selected())
+    m_signal_selection_changed.emit();
+}
+
 void CanvasEditable::remove_all_items()
 {
+  const bool some_selected = !(get_selected_items().empty());
+
   Glib::RefPtr<Goocanvas::Item> root = get_root_item();
   Glib::RefPtr<Goocanvas::Group> root_group = Glib::RefPtr<Goocanvas::Group>::cast_dynamic(root);
-  remove_all_items(root_group);
+
+  while(root_group && root_group->get_n_children())
+      root_group->remove_child(0);
+
+  //The selection has changed because selected items have been removed:
+  if(some_selected)
+    m_signal_selection_changed.emit();
 }
 
 void CanvasEditable::remove_all_items(const Glib::RefPtr<Goocanvas::Group>& group)
 {
+ const bool some_selected = !(get_selected_items().empty());
+
   while(group && group->get_n_children())
       group->remove_child(0);
+
+  //The selection has changed because selected items have been removed:
+  if(some_selected)
+    m_signal_selection_changed.emit();
 }
 
 
@@ -160,4 +187,10 @@ void CanvasEditable::on_item_selected()
   m_signal_selection_changed.emit();
 }
 
+CanvasEditable::type_vec_items CanvasEditable::get_selected_items()
+{
+  //TODO: Provide a default implementation.
+  return type_vec_items();
+}
+
 } //namespace Glom
diff --git a/glom/utility_widgets/canvas/canvas_editable.h b/glom/utility_widgets/canvas/canvas_editable.h
index fdd0285..65e5b30 100644
--- a/glom/utility_widgets/canvas/canvas_editable.h
+++ b/glom/utility_widgets/canvas/canvas_editable.h
@@ -39,6 +39,8 @@ public:
   void add_item(const Glib::RefPtr<Goocanvas::Item>& item, bool resizable = false);
   void add_item(const Glib::RefPtr<Goocanvas::Item>& item, const Glib::RefPtr<Goocanvas::Group>& group, bool resizable = false);
 
+  void remove_item(const Glib::RefPtr<Goocanvas::Item>& item, const Glib::RefPtr<Goocanvas::Group>& group);
+
   void remove_all_items();
   void remove_all_items(const Glib::RefPtr<Goocanvas::Group>& group);
 
@@ -55,6 +57,15 @@ public:
   void add_vertical_rule(double x);
   void add_horizontal_rule(double x);
 
+
+  typedef std::vector< Glib::RefPtr<CanvasItemMovable> > type_vec_items;
+
+  /** Get any items that have get_selected()==true.
+   * Derived classes may override this to only examine items that they consider interesting.
+   */
+  virtual type_vec_items get_selected_items();
+
+
   //TODO: Actually emit this, so we actually show the context menu when clicking on blank space:
   /** void on_show_context(guint button, guint32 activate_time);
    */



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