From e0533e9dd7df504236892fe0d8693e7ad9a6a278 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 3 Jun 2014 15:57:56 -0400 Subject: more profound changes to canvas scrolling, in particular find appropriate ScrollGroup for Canvas::{window,canvas}_to_{canvas,window}() --- libs/canvas/canvas.cc | 65 ++++++++++++++++++++++++--------------- libs/canvas/canvas/canvas.h | 3 +- libs/canvas/canvas/item.h | 4 +++ libs/canvas/canvas/scroll_group.h | 3 ++ libs/canvas/item.cc | 14 +++++++++ libs/canvas/scroll_group.cc | 26 ++++++++++++++++ 6 files changed, 89 insertions(+), 26 deletions(-) (limited to 'libs/canvas') diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index e6feca6416..8638344966 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -207,46 +207,63 @@ Canvas::item_changed (Item* item, boost::optional pre_change_bounding_box) Duple Canvas::window_to_canvas (Duple const & d) const { + /* Find the scroll group that covers d (a window coordinate). Scroll groups are only allowed + * as children of the root group, so we just scan its first level + * children and see what we can find. + */ + + std::list const& root_children (_root.items()); + ScrollGroup* sg = 0; + + for (std::list::const_iterator i = root_children.begin(); i != root_children.end(); ++i) { + if (((sg = dynamic_cast(*i)) != 0) && sg->covers_window (d)) { + break; + } + } + + if (sg) { + return d.translate (sg->scroll_offset()); + } + + /* fallback to global canvas offset ... it would be nice to remove this */ + return d.translate (_scroll_offset); } Duple Canvas::canvas_to_window (Duple const & d, bool rounded) const { - Duple wd = d.translate (-_scroll_offset); + /* Find the scroll group that covers d (a canvas coordinate). Scroll groups are only allowed + * as children of the root group, so we just scan its first level + * children and see what we can find. + */ - /* Note that this intentionally almost always returns integer coordinates */ + std::list const& root_children (_root.items()); + ScrollGroup* sg = 0; + Duple wd; - if (rounded) { - wd.x = round (wd.x); - wd.y = round (wd.y); + for (std::list::const_iterator i = root_children.begin(); i != root_children.end(); ++i) { + if (((sg = dynamic_cast(*i)) != 0) && sg->covers_canvas (d)) { + break; + } } + - return wd; -} - -Rect -Canvas::window_to_canvas (Rect const & r) const -{ - return r.translate (Duple (_scroll_offset.x, _scroll_offset.y)); -} - -Rect -Canvas::canvas_to_window (Rect const & r, bool rounded) const -{ - Rect wr = r.translate (Duple (-_scroll_offset.x, -_scroll_offset.y)); + if (sg) { + wd = d.translate (-sg->scroll_offset()); + } else { + wd = d.translate (-_scroll_offset); + } /* Note that this intentionally almost always returns integer coordinates */ if (rounded) { - wr.x0 = round (wr.x0); - wr.x1 = round (wr.x1); - wr.y0 = round (wr.y0); - wr.y1 = round (wr.y1); + wd.x = round (wd.x); + wd.y = round (wd.y); } - return wr; -} + return wd; +} /** Called when an item has moved. * @param item Item that has moved. diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h index 1f801c3f00..187a773104 100644 --- a/libs/canvas/canvas/canvas.h +++ b/libs/canvas/canvas/canvas.h @@ -90,8 +90,7 @@ public: void item_moved (Item *, boost::optional); virtual Cairo::RefPtr context () = 0; - Rect canvas_to_window (Rect const&, bool rounded = true) const; - Rect window_to_canvas (Rect const&) const; + Duple canvas_to_window (Duple const&, bool rounded = true) const; Duple window_to_canvas (Duple const&) const; diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h index fd41ddd4c5..5483c5124c 100644 --- a/libs/canvas/canvas/item.h +++ b/libs/canvas/canvas/item.h @@ -129,6 +129,10 @@ public: return _position; } + Duple window_origin() const; + + ScrollGroup* scroll_parent() const { return _scroll_parent; } + boost::optional bounding_box () const; Coord height() const; Coord width() const; diff --git a/libs/canvas/canvas/scroll_group.h b/libs/canvas/canvas/scroll_group.h index 2df491e93b..d33e9b9080 100644 --- a/libs/canvas/canvas/scroll_group.h +++ b/libs/canvas/canvas/scroll_group.h @@ -37,6 +37,9 @@ class LIBCANVAS_API ScrollGroup : public Group void scroll_to (Duple const& d); Duple scroll_offset() const { return _scroll_offset; } + bool covers_canvas (Duple const& d) const; + bool covers_window (Duple const& d) const; + private: ScrollSensitivity _scroll_sensitivity; Duple _scroll_offset; diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc index 3b13a12ca8..ddc05a817a 100644 --- a/libs/canvas/item.cc +++ b/libs/canvas/item.cc @@ -82,6 +82,20 @@ Item::~Item () } } +Duple +Item::window_origin () const +{ + /* This is slightly subtle. Our _position is in the coordinate space of + our parent. So to find out where that is in window coordinates, we + have to ask our parent. + */ + if (_parent) { + return _parent->item_to_window (_position); + } else { + return _parent->item_to_window (Duple (0,0)); + } +} + ArdourCanvas::Rect Item::item_to_parent (ArdourCanvas::Rect const & r) const { diff --git a/libs/canvas/scroll_group.cc b/libs/canvas/scroll_group.cc index 76bca50aee..615be8007c 100644 --- a/libs/canvas/scroll_group.cc +++ b/libs/canvas/scroll_group.cc @@ -49,3 +49,29 @@ ScrollGroup::scroll_to (Duple const& d) _scroll_offset.y = d.y; } } + +bool +ScrollGroup::covers_canvas (Duple const& d) const +{ + boost::optional r = bounding_box (); + + if (!r) { + return false; + } + + return r->contains (d); +} + +bool +ScrollGroup::covers_window (Duple const& d) const +{ + boost::optional r = bounding_box (); + + if (!r) { + return false; + } + + Rect w = r->translate (-_scroll_offset); + + return w.contains (d); +} -- cgit v1.2.3