[glom] Print Layout: Allow the user to select items with a click.



commit 8ea71e2e1ab103486061a3ebf865a2e8149c9241
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Aug 5 20:43:56 2011 +0200

    Print Layout: Allow the user to select items with a click.
    
    * glom/utility_widgets/canvas/canvas_item_movable.[h|cc]:
    Added get/set_selected() and a virtual show_selected() which it calls.
    on_button_release_event(): set the item as
    - selected if it unselected and the clicked without a move.
    - unselected if it was selected and clicked without a move.
    - selected if it was moved.
    This is roughly like Inkscape's behaviour.
    * glom/utility_widgets/canvas/canvas_group_resizable.[h|cc]:
    Split the manipulator group into two groups (edges and corners),
    so we can (re)use the edges to show selection.
    Implement show_selected() to show/hide the edges.
    set_manipulator_visibility(): Make sure that we don't hide the
    edges that are visible to show selection.
    
    This doesn't actuall do anything useful yet, but it will let us
    do things to the selected item(s), such as editing their position via
    coordinate numbers, moving them together, or copy/paste/cut/deleting
    them via the menus.

 ChangeLog                                          |   23 +++++
 .../print_layouts/window_print_layout_edit.cc      |    2 +-
 .../canvas/canvas_group_resizable.cc               |   89 +++++++++++++++-----
 .../canvas/canvas_group_resizable.h                |    4 +-
 glom/utility_widgets/canvas/canvas_item_movable.cc |   40 +++++++++-
 glom/utility_widgets/canvas/canvas_item_movable.h  |   15 ++++
 6 files changed, 148 insertions(+), 25 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f23d3a9..db323ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2011-08-05  Murray Cumming  <murrayc murrayc com>
 
+	Print Layout: Allow the user to select items with a click.
+
+	* glom/utility_widgets/canvas/canvas_item_movable.[h|cc]: 
+	Added get/set_selected() and a virtual show_selected() which it calls.
+	on_button_release_event(): set the item as 
+	- selected if it unselected and the clicked without a move.
+	- unselected if it was selected and clicked without a move.
+	- selected if it was moved.
+	This is roughly like Inkscape's behaviour.
+	* glom/utility_widgets/canvas/canvas_group_resizable.[h|cc]:
+	Split the manipulator group into two groups (edges and corners), 
+	so we can (re)use the edges to show selection.
+	Implement show_selected() to show/hide the edges.
+	set_manipulator_visibility(): Make sure that we don't hide the 
+	edges that are visible to show selection.
+
+	This doesn't actuall do anything useful yet, but it will let us 
+	do things to the selected item(s), such as editing their position via 
+	coordinate numbers, moving them together, or copy/paste/cut/deleting 
+	them via the menus.
+
+2011-08-05  Murray Cumming  <murrayc murrayc com>
+
 	Print Layout: Avoid warnings about -1 width.
 
 	* glom/utility_widgets/canvas/canvas_group_movable.cc: get_width_height(),
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 0e0536f..87cf6b0 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.cc
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.cc
@@ -395,7 +395,7 @@ sharedptr<LayoutItem> Window_PrintLayout_Edit::create_empty_item(PrintLayoutTool
     sharedptr<LayoutItem_Text> layout_item_derived = sharedptr<LayoutItem_Text>::create();
 
     // Note to translators: This is the default contents of a text item on a print layout: 
-    layout_item_derived->set_text(_("text"));
+    layout_item_derived->set_text(_("text")); //TODO: Choose some other longer default because this is hidden under the drag icon?
     layout_item = layout_item_derived;
     layout_item->set_print_layout_position(0, 0, 50, 10);
   }
diff --git a/glom/utility_widgets/canvas/canvas_group_resizable.cc b/glom/utility_widgets/canvas/canvas_group_resizable.cc
index 29ba63a..c35ccde 100644
--- a/glom/utility_widgets/canvas/canvas_group_resizable.cc
+++ b/glom/utility_widgets/canvas/canvas_group_resizable.cc
@@ -48,11 +48,17 @@ CanvasGroupResizable::CanvasGroupResizable()
 void CanvasGroupResizable::create_manipulators()
 {
   //Remove any existing manipulators:
-  if(m_group_manipulators)
-    m_group_manipulators->remove();
+  if(m_group_edge_manipulators)
+    m_group_edge_manipulators->remove();
+
+  if(m_group_corner_manipulators)
+    m_group_corner_manipulators->remove();
   
-  m_group_manipulators = Goocanvas::Group::create();
-  add_child(m_group_manipulators);
+  m_group_edge_manipulators = Goocanvas::Group::create();
+  add_child(m_group_edge_manipulators);
+
+  m_group_corner_manipulators = Goocanvas::Group::create();
+  add_child(m_group_corner_manipulators);
 
   if(get_is_line())
     create_line_manipulators();
@@ -89,14 +95,14 @@ void CanvasGroupResizable::create_rect_manipulators()
   m_manipulator_edge_left = create_edge_manipulator();
   m_manipulator_edge_right = create_edge_manipulator();
 
-  m_group_manipulators->add_child(m_manipulator_corner_top_left);
-  m_group_manipulators->add_child(m_manipulator_corner_top_right);
-  m_group_manipulators->add_child(m_manipulator_corner_bottom_left);
-  m_group_manipulators->add_child(m_manipulator_corner_bottom_right);
-  m_group_manipulators->add_child(m_manipulator_edge_top);
-  m_group_manipulators->add_child(m_manipulator_edge_bottom);
-  m_group_manipulators->add_child(m_manipulator_edge_left);
-  m_group_manipulators->add_child(m_manipulator_edge_right);
+  m_group_corner_manipulators->add_child(m_manipulator_corner_top_left);
+  m_group_corner_manipulators->add_child(m_manipulator_corner_top_right);
+  m_group_corner_manipulators->add_child(m_manipulator_corner_bottom_left);
+  m_group_corner_manipulators->add_child(m_manipulator_corner_bottom_right);
+  m_group_edge_manipulators->add_child(m_manipulator_edge_top);
+  m_group_edge_manipulators->add_child(m_manipulator_edge_bottom);
+  m_group_edge_manipulators->add_child(m_manipulator_edge_left);
+  m_group_edge_manipulators->add_child(m_manipulator_edge_right);
 
   m_manipulator_corner_top_left->set_grid(m_grid);
   m_manipulator_corner_top_left->set_snap_corner(CanvasRectMovable::CORNER_TOP_LEFT);
@@ -134,8 +140,11 @@ void CanvasGroupResizable::create_line_manipulators()
 {
   m_manipulator_start = create_corner_manipulator();
   m_manipulator_end = create_corner_manipulator();
-  m_group_manipulators->add_child(m_manipulator_start);
-  m_group_manipulators->add_child(m_manipulator_end);
+
+  //We add these to the edge manipulators, though they look like 
+  //corner manipulators, because we want to use them to show selection.
+  m_group_edge_manipulators->add_child(m_manipulator_start);
+  m_group_edge_manipulators->add_child(m_manipulator_end);
 
   m_manipulator_start->set_grid(m_grid);
   //m_manipulator_corner_top_left->set_snap_corner(CanvasRectMovable::CORNER_TOP_LEFT);
@@ -215,12 +224,14 @@ void CanvasGroupResizable::position_rect_manipulators()
   //and the manipulators are above the item (and above the rect):
   if(item)
   {
-    m_group_manipulators->raise(item);
+    m_group_edge_manipulators->raise(item);
+    m_group_corner_manipulators->raise(item);
     m_rect->lower(item);
   }
   else
   {
-    m_group_manipulators->raise(m_rect);
+    m_group_edge_manipulators->raise(m_rect);
+    m_group_corner_manipulators->raise(m_rect);
   }
 }
 
@@ -247,7 +258,8 @@ void CanvasGroupResizable::position_line_manipulators()
 
   m_manipulator_end->set_xy(end_x - half_size, end_y - half_size); //Center it over the point.
 
-  m_group_manipulators->raise(line);
+  m_group_edge_manipulators->raise(line);
+  m_group_corner_manipulators->raise(line);
 }
 
 void CanvasGroupResizable::set_child(const Glib::RefPtr<CanvasItemMovable>& child)
@@ -638,11 +650,18 @@ bool CanvasGroupResizable::on_manipulator_motion_notify_event(const Glib::RefPtr
 
 void CanvasGroupResizable::set_manipulators_visibility(Goocanvas::ItemVisibility visibility)
 {
-  if(!m_group_manipulators)
+  if(!m_group_edge_manipulators || !m_group_corner_manipulators)
     return;
 
+  //Make sure that edges stays visible if the item is selected,
+  //because that is how we show selection:
+  Goocanvas::ItemVisibility edge_visibility = visibility;
+  if(get_selected())
+    edge_visibility = Goocanvas::ITEM_VISIBLE;
+
   //For testing: visibility = Goocanvas::ITEM_VISIBLE;
-  m_group_manipulators->property_visibility() = visibility;
+  m_group_edge_manipulators->property_visibility() = edge_visibility;
+  m_group_corner_manipulators->property_visibility() = visibility;
 }
 
 bool CanvasGroupResizable::on_rect_enter_notify_event(const Glib::RefPtr<Goocanvas::Item>& /* target */, GdkEventCrossing* /* event */)
@@ -869,13 +888,24 @@ void CanvasGroupResizable::set_grid(const Glib::RefPtr<const CanvasGroupGrid>& g
   CanvasItemMovable::set_grid(grid);
 
   //Apply the grid to all the manipulators:
-  if(!m_group_manipulators)
+  if(!m_group_edge_manipulators || !m_group_corner_manipulators)
     return;
 
-  const int count = m_group_manipulators->get_n_children();
+  int count = m_group_edge_manipulators->get_n_children();
+  for(int i = 0; i < count; ++i)
+  {
+    Glib::RefPtr<Goocanvas::Item> child = m_group_edge_manipulators->get_child(i);
+    Glib::RefPtr<CanvasItemMovable> movable = CanvasItemMovable::cast_to_movable(child);
+    if(movable)
+    {
+      movable->set_grid(grid);
+    }
+  }
+
+  count = m_group_corner_manipulators->get_n_children();
   for(int i = 0; i < count; ++i)
   {
-    Glib::RefPtr<Goocanvas::Item> child = m_group_manipulators->get_child(i);
+    Glib::RefPtr<Goocanvas::Item> child = m_group_corner_manipulators->get_child(i);
     Glib::RefPtr<CanvasItemMovable> movable = CanvasItemMovable::cast_to_movable(child);
     if(movable)
     {
@@ -884,6 +914,21 @@ void CanvasGroupResizable::set_grid(const Glib::RefPtr<const CanvasGroupGrid>& g
   }
 }
 
+void CanvasGroupResizable::show_selected()
+{
+  if(!m_group_edge_manipulators)
+    return;
+
+  Goocanvas::ItemVisibility edge_visibility = Goocanvas::ITEM_INVISIBLE;
+  if(get_selected())
+    edge_visibility = Goocanvas::ITEM_VISIBLE;
+
+  //This is also set the same way if set_manipulators_visibility(),
+  //in case that is called at some other time.
+  m_group_edge_manipulators->property_visibility() = edge_visibility;
+}
+
+
 
 } //namespace Glom
 
diff --git a/glom/utility_widgets/canvas/canvas_group_resizable.h b/glom/utility_widgets/canvas/canvas_group_resizable.h
index dfda646..29c86b2 100644
--- a/glom/utility_widgets/canvas/canvas_group_resizable.h
+++ b/glom/utility_widgets/canvas/canvas_group_resizable.h
@@ -68,6 +68,7 @@ public:
   type_signal_resized signal_resized();
 
 private:
+  virtual void show_selected();
   virtual Goocanvas::Canvas* get_parent_canvas_widget();
 
   virtual void snap_position(double& x, double& y) const;
@@ -144,7 +145,8 @@ private:
 
   Glib::RefPtr<CanvasItemMovable> m_child;
 
-  Glib::RefPtr<Goocanvas::Group> m_group_manipulators; //not including the rect.
+  Glib::RefPtr<Goocanvas::Group> m_group_edge_manipulators; //not including the rect.
+  Glib::RefPtr<Goocanvas::Group> m_group_corner_manipulators; //not including the rect.
 
   //Manipulators for a rectangle:
   Glib::RefPtr<Goocanvas::Rect> m_rect; //Something to get events on, because m_child might actually be smaller than indicated by our manipulators.
diff --git a/glom/utility_widgets/canvas/canvas_item_movable.cc b/glom/utility_widgets/canvas/canvas_item_movable.cc
index 263f20e..c0f3490 100644
--- a/glom/utility_widgets/canvas/canvas_item_movable.cc
+++ b/glom/utility_widgets/canvas/canvas_item_movable.cc
@@ -42,7 +42,8 @@ CanvasItemMovable::CanvasItemMovable()
   m_drag_start_cursor_x(0.0), m_drag_start_cursor_y(0.0),
   m_drag_start_position_x(0.0), m_drag_start_position_y(0.0),
   m_grid(0),
-  m_allow_vertical_movement(true), m_allow_horizontal_movement(true)
+  m_allow_vertical_movement(true), m_allow_horizontal_movement(true),
+  m_selected(false)
 {
    //TODO: Remove this when goocanvas is fixed, so the goocanvasmm constructor can connect default signal handlers:
   /*
@@ -168,6 +169,26 @@ bool CanvasItemMovable::on_button_release_event(const Glib::RefPtr<Goocanvas::It
 
   m_dragging = false;
 
+
+  // A click without a move should select or deselect:
+  bool selected = !get_selected();
+
+  // A drag-to-move should always select and never deselect:
+  if(!selected)
+  {
+    double x = 0;
+    double y = 0;
+    get_xy(x, y);
+    if( (m_drag_start_position_x != x)
+      || (m_drag_start_position_y != y) )
+    {
+      selected = true;
+    }
+  }
+
+  //This will also ask derived classes to indicate it visually:
+  set_selected(selected);
+
   return true;
 }
 
@@ -373,5 +394,22 @@ Glib::RefPtr<const Goocanvas::Item> CanvasItemMovable::cast_const_to_item(const
   return cast_to_item(unconst);
 }
 
+void CanvasItemMovable::set_selected(bool selected)
+{
+  m_selected = selected;
+  show_selected(); //Let derived classes indicate it visually,
+}
+
+bool CanvasItemMovable::get_selected() const
+{
+  return m_selected;
+}
+
+void CanvasItemMovable::show_selected()
+{
+  //Derived classes should override this.
+}
+
+
 } //namespace Glom
 
diff --git a/glom/utility_widgets/canvas/canvas_item_movable.h b/glom/utility_widgets/canvas/canvas_item_movable.h
index bd1f8f4..a3846ca 100644
--- a/glom/utility_widgets/canvas/canvas_item_movable.h
+++ b/glom/utility_widgets/canvas/canvas_item_movable.h
@@ -91,8 +91,22 @@ public:
 
   virtual void snap_position(double& x, double& y) const;
 
+  /** Mark the item as selected,
+   * meaning that its boundaries will be visible,
+   * and this can be queried later, for instance to move several items together.
+   */
+  void set_selected(bool selected = true);
+
+  bool get_selected() const;
+
 private:
 
+  /** Show some visual cue that the item is selected,
+   * depending on the value of get_selected(),
+   * hiding that visual cue if it is not selected.
+   */
+  virtual void show_selected();
+
   virtual Goocanvas::Canvas* get_parent_canvas_widget() = 0;
 
   void set_cursor(const Glib::RefPtr<Gdk::Cursor>& cursor);
@@ -118,6 +132,7 @@ protected:
 
 private:
   bool m_allow_vertical_movement, m_allow_horizontal_movement;
+  bool m_selected;
 
   type_signal_moved m_signal_moved;
   type_signal_show_context m_signal_show_context;



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