diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index f29bdba72c..9f37529960 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -80,7 +80,7 @@ Canvas::zoomed () } /** Render an area of the canvas. - * @param area Area in canvas coordinates. + * @param area Area in window coordinates. * @param context Cairo context to render to. */ void @@ -207,13 +207,13 @@ Canvas::item_changed (Item* item, boost::optional pre_change_bounding_box) Duple Canvas::window_to_canvas (Duple const & d) const { - return d.translate (Duple (_scroll_offset.x, _scroll_offset.y)); + return d.translate (_scroll_offset); } Duple Canvas::canvas_to_window (Duple const & d, bool rounded) const { - Duple wd = d.translate (Duple (-_scroll_offset.x, -_scroll_offset.y)); + Duple wd = d.translate (-_scroll_offset); /* Note that this intentionally almost always returns integer coordinates */ @@ -283,9 +283,7 @@ Canvas::item_moved (Item* item, boost::optional pre_change_parent_bounding void Canvas::queue_draw_item_area (Item* item, Rect area) { - ArdourCanvas::Rect canvas_area = item->item_to_canvas (area); - // cerr << "CANVAS " << this << " for " << item << ' ' << item->whatami() << ' ' << item->name << " invalidate " << area << " TRANSLATE AS " << canvas_area << " window = " << canvas_to_window (canvas_area) << std::endl; - request_redraw (canvas_area); + request_redraw (item->item_to_window (area)); } /** Construct a GtkCanvas */ @@ -750,18 +748,12 @@ GtkCanvas::on_leave_notify_event (GdkEventCrossing* ev) } /** Called to request a redraw of our canvas. - * @param area Area to redraw, in canvas coordinates. + * @param area Area to redraw, in window coordinates. */ void GtkCanvas::request_redraw (Rect const & request) { - boost::optional req = request.intersection (visible_area()); - - if (req) { - Rect r = req.get(); - Rect area = canvas_to_window (r); - queue_draw_area (area.x0, area.y0, area.width(), area.height()); - } + queue_draw_area (request.x0, request.y0, request.width(), request.height()); } /** Called to request that we try to get a particular size for ourselves. diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h index 3f7d6fd519..1f801c3f00 100644 --- a/libs/canvas/canvas/canvas.h +++ b/libs/canvas/canvas/canvas.h @@ -61,7 +61,7 @@ public: Canvas (); virtual ~Canvas () {} - /** called to request a redraw of an area of the canvas */ + /** called to request a redraw of an area of the canvas in WINDOW coordinates */ virtual void request_redraw (Rect const &) = 0; /** called to ask the canvas to request a particular size from its host */ virtual void request_size (Duple) = 0; @@ -90,7 +90,6 @@ 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; @@ -109,6 +108,7 @@ public: } void scroll_to (Coord x, Coord y); + Duple scroll_offset() const { return _scroll_offset; } void add_scroller (ScrollGroup& i); virtual Rect visible_area () const = 0; diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h index 2b873ee1fc..aa9796a288 100644 --- a/libs/canvas/canvas/item.h +++ b/libs/canvas/canvas/item.h @@ -37,6 +37,7 @@ namespace ArdourCanvas class Canvas; class Group; class Rect; +class ScrollGroup; /** The parent class for anything that goes on the canvas. * @@ -119,10 +120,6 @@ public: return _position; } - virtual Duple canvas_position () const { - return _position; - } - boost::optional bounding_box () const; Coord height() const; Coord width() const; @@ -224,6 +221,8 @@ protected: Canvas* _canvas; /** parent group; may be 0 if we are the root group or if we have been unparent()ed */ Group* _parent; + /** scroll parent group; may be 0 if we are the root group or if we have been unparent()ed */ + ScrollGroup* _scroll_parent; /** position of this item in parent coordinates */ Duple _position; /** true if this item is visible (ie to be drawn), otherwise false */ @@ -246,6 +245,8 @@ private: Duple scroll_offset() const; Duple position_offset() const; + + void find_scroll_parent (); }; extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&); diff --git a/libs/canvas/canvas/scroll_group.h b/libs/canvas/canvas/scroll_group.h index 36d98538a1..2df491e93b 100644 --- a/libs/canvas/canvas/scroll_group.h +++ b/libs/canvas/canvas/scroll_group.h @@ -35,16 +35,8 @@ class LIBCANVAS_API ScrollGroup : public Group explicit ScrollGroup (Group *, Duple, ScrollSensitivity); void scroll_to (Duple const& d); - - /** return the normal "base" position of this item - rather its position as affected by any scroll - offset. - */ - Duple canvas_position() const { - return _position.translate (_scroll_offset); - } - Duple scroll_offset() const { return _scroll_offset; } + private: ScrollSensitivity _scroll_sensitivity; Duple _scroll_offset; diff --git a/libs/canvas/group.cc b/libs/canvas/group.cc index 509be0b51a..95fdbc8c62 100644 --- a/libs/canvas/group.cc +++ b/libs/canvas/group.cc @@ -61,7 +61,7 @@ Group::~Group () clear_items (true); } -/** @param area Area to draw in this group's coordinates. +/** @param area Area to draw in window coordinates. * @param context Context, set up with its origin at this group's position. */ void diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc index 3ca73bbf9f..0706df6bae 100644 --- a/libs/canvas/item.cc +++ b/libs/canvas/item.cc @@ -66,6 +66,8 @@ Item::init () _parent->add (this); } + find_scroll_parent (); + DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); } @@ -89,18 +91,10 @@ Item::item_to_parent (ArdourCanvas::Rect const & r) const Duple Item::scroll_offset () const { - Item const * i = this; - Duple offset; - - while (i) { - ScrollGroup const * sg = dynamic_cast (i); - if (sg) { - offset = offset.translate (sg->scroll_offset()); - } - i = i->parent(); - } - - return offset; + if (_scroll_parent) { + return _scroll_parent->scroll_offset(); + } + return _canvas->scroll_offset(); } Duple @@ -110,7 +104,7 @@ Item::position_offset() const Duple offset; while (i) { - offset = offset.translate (i->canvas_position()); + offset = offset.translate (i->position()); i = i->parent(); } @@ -163,7 +157,12 @@ Item::canvas_to_item (Coord& x, Coord& y) const Duple Item::item_to_window (ArdourCanvas::Duple const & d, bool rounded) const { - return item_to_canvas (d).translate (-scroll_offset()); + Duple ret = item_to_canvas (d).translate (-scroll_offset()); + + ret.x = round (ret.x); + ret.y = round (ret.y); + + return ret; } Duple @@ -175,7 +174,14 @@ Item::window_to_item (ArdourCanvas::Duple const & d) const ArdourCanvas::Rect Item::item_to_window (ArdourCanvas::Rect const & r) const { - return item_to_canvas (r).translate (-scroll_offset()); + Rect ret = item_to_canvas (r).translate (-scroll_offset()); + + ret.x0 = round (ret.x0); + ret.x1 = round (ret.x1); + ret.y0 = round (ret.y0); + ret.y1 = round (ret.y1); + + return ret; } ArdourCanvas::Rect @@ -284,6 +290,7 @@ void Item::unparent () { _parent = 0; + _scroll_parent = 0; } void @@ -299,9 +306,29 @@ Item::reparent (Group* new_parent) _parent = new_parent; _canvas = _parent->canvas (); + + find_scroll_parent (); + _parent->add (this); } +void +Item::find_scroll_parent () +{ + Item const * i = this; + ScrollGroup const * last_scroll_group = 0; + + while (i) { + ScrollGroup const * sg = dynamic_cast (i); + if (sg) { + last_scroll_group = sg; + } + i = i->parent(); + } + + _scroll_parent = const_cast (last_scroll_group); +} + bool Item::common_ancestor_within (uint32_t limit, const Item& other) const { @@ -444,7 +471,7 @@ void Item::redraw () const { if (_visible && _bounding_box && _canvas) { - _canvas->request_redraw (item_to_canvas (_bounding_box.get())); + _canvas->request_redraw (item_to_window (_bounding_box.get())); } } diff --git a/libs/canvas/scroll_group.cc b/libs/canvas/scroll_group.cc index 94ea869971..76bca50aee 100644 --- a/libs/canvas/scroll_group.cc +++ b/libs/canvas/scroll_group.cc @@ -17,6 +17,10 @@ */ #include + +#include "pbd/compose.h" + +#include "canvas/debug.h" #include "canvas/scroll_group.h" using namespace std; @@ -37,26 +41,11 @@ ScrollGroup::ScrollGroup (Group* parent, Duple position, ScrollSensitivity s) void ScrollGroup::scroll_to (Duple const& d) { - /* get the nominal position of the group without scroll being in effect - */ - - Duple base_pos (_position.translate (_scroll_offset)); - - /* compute a new position given our sensitivity to h- and v-scrolling - */ - if (_scroll_sensitivity & ScrollsHorizontally) { - base_pos.x -= d.x; _scroll_offset.x = d.x; } if (_scroll_sensitivity & ScrollsVertically) { - base_pos.y -= d.y; _scroll_offset.y = d.y; } - - /* move there */ - - set_position (base_pos); } -