a few changes to fix region dragging, all related to coordinate system handling,...
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 15 Apr 2013 14:38:12 +0000 (10:38 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 15 Apr 2013 14:38:12 +0000 (10:38 -0400)
gtk2_ardour/editor.h
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/public_editor.h
gtk2_ardour/tempo_lines.cc
gtk2_ardour/time_axis_view.cc
libs/canvas/canvas.cc
libs/canvas/canvas/item.h
libs/canvas/group.cc
libs/canvas/item.cc

index a508e1d08021c55bd21eb8e0307cf724f006a36b..558f24f31ce09386e1d904f0f32974a331171422 100644 (file)
@@ -1016,8 +1016,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        bool deferred_control_scroll (framepos_t);
        sigc::connection control_scroll_connection;
 
-       gdouble get_trackview_group_vertical_offset () const { return vertical_adjustment.get_value (); }
-
        ArdourCanvas::Group* get_background_group () const { return _background_group; }
        ArdourCanvas::Group* get_trackview_group () const { return _trackview_group; }
        void tie_vertical_scrolling ();
index 3f0098dcd0a6fc5d0c416f436b5015e7aa98c0c5..faaae52ff60c85a7b58c3539f29e5605cb659ac7 100644 (file)
@@ -33,6 +33,7 @@
 #include "canvas/rectangle.h"
 #include "canvas/pixbuf.h"
 #include "canvas/text.h"
+#include "canvas/debug.h"
 
 #include "ardour_ui.h"
 #include "editor.h"
@@ -101,10 +102,14 @@ Editor::initialize_canvas ()
 
 
        _background_group = new ArdourCanvas::Group (_track_canvas->root());
+       CANVAS_DEBUG_NAME (_background_group, "Canvas Background");
        _master_group = new ArdourCanvas::Group (_track_canvas->root());
+       CANVAS_DEBUG_NAME (_master_group, "Canvas Master");
 
        _trackview_group = new ArdourCanvas::Group (_master_group);
+       CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
        _region_motion_group = new ArdourCanvas::Group (_trackview_group);
+       CANVAS_DEBUG_NAME (_region_motion_group, "Canvas Region Motion");
 
        meter_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        meter_bar = new ArdourCanvas::Rectangle (meter_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
@@ -487,7 +492,7 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool moving_left, b
        /* Note whether we're fudging the autoscroll (see autoscroll_fudge_threshold) */
        _autoscroll_fudging = (distance < autoscroll_fudge_threshold ());
 
-       double const ty = _drags->current_pointer_y() - get_trackview_group_vertical_offset ();
+       double const ty = _drags->current_pointer_y();
 
        autoscroll_y = 0;
        autoscroll_x = 0;
@@ -558,7 +563,7 @@ Editor::autoscroll_canvas ()
 
        if (autoscroll_y_distance != 0) {
                if (autoscroll_y > 0) {
-                       autoscroll_y_distance = (_drags->current_pointer_y() - (get_trackview_group_vertical_offset() + _visible_canvas_height)) / 3;
+                       autoscroll_y_distance = (_drags->current_pointer_y() - _visible_canvas_height) / 3;
                } else if (autoscroll_y < 0) {
 
                        autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3;
@@ -754,23 +759,6 @@ Editor::set_horizontal_position (double p)
        HorizontalPositionChanged (); /* EMIT SIGNAL */
 }
 
-// CAIROCANVAS
-#if 0
-void
-Editor::scroll_canvas_vertically ()
-{
-       /* vertical scrolling only */
-
-       double y_delta;
-
-       y_delta = last_trackview_group_vertical_offset - get_trackview_group_vertical_offset ();
-       _trackview_group->move (0, y_delta);
-       _background_group->move (0, y_delta);
-
-       last_trackview_group_vertical_offset = get_trackview_group_vertical_offset ();
-}
-#endif
-
 void
 Editor::color_handler()
 {
index d753d59551a82f35e57cd57e8d61a88ff9f9c952..1b9a820ae6423629f5d4a08ea9790da8e7783fab 100644 (file)
@@ -670,12 +670,16 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
                        /* Reparent to a non scrolling group so that we can keep the
                           region selection above all time axis views.
                           Reparenting means that we will have to move the region view
-                          later, as the two parent groups have different coordinates.
+                          within its new parent, as the two parent groups have different coordinates.
                        */
 
+                       ArdourCanvas::Group* rvg = rv->get_canvas_group();
+                       Duple rv_canvas_offset = rvg->item_to_canvas (Duple (0,0));
+
                        rv->get_canvas_group()->reparent (_editor->_region_motion_group);
-                       
+
                        rv->fake_set_opaque (true);
+                       rvg->set_position (rv_canvas_offset);
                }
 
                /* If we have moved tracks, we'll fudge the layer delta so that the
@@ -725,8 +729,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
 
                        /* Get the y coordinate of the top of the track that this region is now on */
                        tv->canvas_display()->item_to_canvas (x, y);
-                       y += _editor->get_trackview_group_vertical_offset();
-                       
+
                        /* And adjust for the layer that it should be on */
                        StreamView* cv = tv->view ();
                        switch (cv->layer_display ()) {
index 30aab87d05191a2dfef6b22b8593c592ffc00df3..b717ef5464871a74e13234190da4837e614a1ed2 100644 (file)
@@ -193,9 +193,8 @@ Editor::draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
        if (tempo_lines == 0) {
                tempo_lines = new TempoLines (*_track_canvas_viewport, time_line_group, physical_screen_height(get_window()));
        }
-
-       // CAIROCANVAS
-       // tempo_lines->draw (begin, end, frames_per_unit);
+       
+       tempo_lines->draw (begin, end, samples_per_pixel);
 }
 
 void
index 9fbf4533b4c661cdc3c01a135253d517872585fc..42ff531a3579e7ccbd454c3c7127e93ed86ee66e 100644 (file)
@@ -380,7 +380,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
        virtual Gtk::HBox& get_status_bar_packer() = 0;
 #endif
 
-       virtual gdouble get_trackview_group_vertical_offset () const = 0;
        virtual ArdourCanvas::Group* get_trackview_group () const = 0;
        virtual ArdourCanvas::Group* get_background_group () const = 0;
 
index 5cb059cbee5a0680ee4a5166937fc239b1deee1d..cd923d88a9c1af863c9180ac04ceb99b39e2170b 100644 (file)
@@ -123,11 +123,11 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
        // Tempo map hasn't changed and we're entirely within a clean
        // range, don't need to do anything.  Yay.
        if (needed_left >= _clean_left && needed_right <= _clean_right) {
-               // cout << endl << "*** LINE CACHE PERFECT HIT" << endl;
+               // cerr << endl << "*** LINE CACHE PERFECT HIT" << endl;
                return;
        }
 
-       //cout << endl << "*** LINE CACHE MISS" << endl;
+       // cerr << endl << "*** LINE CACHE MISS" << endl;
 
        bool invalidated = false;
 
@@ -169,7 +169,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
                        
                        // Steal from the right
                        if (left->first > needed_left && li != steal && steal->first > needed_right) {
-                               //cout << "*** STEALING FROM RIGHT" << endl;
+                               // cerr << "*** STEALING FROM RIGHT" << endl;
                                double const x = steal->first;
                                line = steal->second;
                                _lines.erase(steal);
@@ -208,7 +208,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
                        
                        // Create a new line
                } else if (_lines.size() < needed || _lines.size() < MAX_CACHED_LINES) {
-                       //cout << "*** CREATING LINE" << endl;
+                       // cerr << "*** CREATING LINE" << endl;
                        /* if we already have a line there ... don't sweat it */
                        if (_lines.find (xpos) == _lines.end()) {
                                line = new ArdourCanvas::Line (_group);
@@ -222,7 +222,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
                        
                        // Steal from the left
                } else {
-                       //cout << "*** STEALING FROM LEFT" << endl;
+                       // cerr << "*** STEALING FROM LEFT" << endl;
                        if (_lines.find (xpos) == _lines.end()) {
                                Lines::iterator steal = _lines.begin();
                                double const x = steal->first;
index 433eee350d915cfe374a782ce429b907e76bb694..a426656cf652ab8d4679d084cfbc1e0b973c63bb 100644 (file)
@@ -373,7 +373,7 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev)
                */
                int tx, ty;
                controls_ebox.translate_coordinates (*control_parent, ev->x, ev->y, tx, ty);
-               ev->y = ty - _editor.get_trackview_group_vertical_offset();
+               ev->y = ty;
                _editor.drags()->motion_handler ((GdkEvent *) ev, false);
                _editor.maybe_autoscroll (false, true, false, ev->y_root < _resize_drag_start);
 
index b849894bf04dbe5bbc6cccdac3718c980426207f..da34a73c211953d434685b09fa96a5492b91fce2 100644 (file)
@@ -100,18 +100,6 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
        // checkpoint ("render", "-> render");
        render_count = 0;
        
-#ifdef CANVAS_DEBUG
-       if (getenv ("ARDOUR_HARLEQUIN_CANVAS")) {
-               /* light up the canvas to show redraws */
-               context->set_source_rgba (random()%255 / 255.0,
-                                         random()%255 / 255.0,
-                                         random()%255 / 255.0,
-                                         255);
-               context->rectangle (area.x0, area.y0, area.width(), area.height());
-               context->fill ();
-       }
-#endif
-
        context->save ();
 
        /* clip to the requested area */
@@ -143,6 +131,17 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
 
        context->restore ();
 
+#ifdef CANVAS_DEBUG
+       if (getenv ("ARDOUR_HARLEQUIN_CANVAS")) {
+               /* light up the canvas to show redraws */
+               context->set_source_rgba (random()%255 / 255.0,
+                                         random()%255 / 255.0,
+                                         random()%255 / 255.0,
+                                         255);
+               context->rectangle (area.x0, area.y0, area.width(), area.height());
+               context->fill ();
+       }
+#endif
        // checkpoint ("render", "<- render");
 }
 
@@ -225,10 +224,15 @@ void
 Canvas::item_moved (Item* item, boost::optional<Rect> pre_change_parent_bounding_box)
 {
        if (pre_change_parent_bounding_box) {
-               /* request a redraw of where the item used to be; we have to use the
-                  parent's coordinates here as item bounding boxes do not change
-                  when the item moves.
-               */
+               /* request a redraw of where the item used to be. The box has
+                * to be in parent coordinate space since the bounding box of
+                * an item does not change when moved. If we use
+                * item->item_to_canvas() on the old bounding box, we will be
+                * using the item's new position, and so will compute the wrong
+                * invalidation area. If we use the parent (which has not
+                * moved, then this will work.
+                */
+
                queue_draw_item_area (item->parent(), pre_change_parent_bounding_box.get ());
        }
 
@@ -246,7 +250,9 @@ Canvas::item_moved (Item* item, boost::optional<Rect> pre_change_parent_bounding
 void
 Canvas::queue_draw_item_area (Item* item, Rect area)
 {
-       request_redraw (item->item_to_canvas (area));
+       ArdourCanvas::Rect canvas_area = item->item_to_canvas (area);
+       // cerr << "CANVAS Invalidate " << area << " TRANSLATE AS " << canvas_area << endl;
+       request_redraw (canvas_area);
 }
 
 /** @return An XML description of the canvas and its objects */
@@ -554,6 +560,7 @@ void
 GtkCanvas::request_redraw (Rect const & request)
 {
        Rect area = canvas_to_window (request);
+       // cerr << "Invalidate " << request << " TRANSLATE AS " << area << endl;
        queue_draw_area (floor (area.x0), floor (area.y0), ceil (area.x1) - floor (area.x0), ceil (area.y1) - floor (area.y0));
 }
 
index fc66754ed4ba20334cf29d69fee48b771f809f03..7f1321b260da1b9f4e760b52e0f01b39be1dbdfd 100644 (file)
@@ -108,9 +108,12 @@ public:
        /* XXX: it's a pity these aren't the same form as item_to_parent etc.,
           but it makes a bit of a mess in the rest of the code if they are not.
        */
-       void canvas_to_item (Coord &, Coord &) const;
+
+        void canvas_to_item (Coord &, Coord &) const;
+        Duple canvas_to_item (Duple const &) const;
        void item_to_canvas (Coord &, Coord &) const;
        Rect item_to_canvas (Rect const &) const;
+        Duple item_to_canvas (Duple const &) const;
 
        void raise_to_top ();
        void raise (int);
index d12c13169ed9be87d18752a52ebe97ab3b7ae819..34001bc255ca2b6a4dadaefa7ddac512f8937d78 100644 (file)
@@ -278,6 +278,7 @@ Group::dump (ostream& o) const
 {
        o << _canvas->indent();
        o << "Group " << this << " [" << name << ']';
+       o << " @ " << position();
        o << " Items: " << _items.size();
        o << " Visible ? " << _visible;
 
@@ -285,6 +286,7 @@ Group::dump (ostream& o) const
 
        if (bb) {
                o << endl << _canvas->indent() << "  bbox: " << bb.get();
+               o << endl << _canvas->indent() << "  CANVAS bbox: " << item_to_canvas (bb.get());
        } else {
                o << "  bbox unset";
        }
index 2c4ec893e761a97fbf0e31a8e46483f56d668459..75a5718271af928eb54a5f08813c9a1ffce066c7 100644 (file)
@@ -67,6 +67,66 @@ Item::item_to_parent (ArdourCanvas::Rect const & r) const
        return r.translate (_position);
 }
 
+ArdourCanvas::Rect
+Item::item_to_canvas (ArdourCanvas::Rect const & r) const
+{
+       Item const * i = this;
+       Duple offset;
+
+       while (i) {
+               offset = offset.translate (i->position());
+               i = i->parent();
+       }
+
+       return r.translate (offset);
+}
+
+ArdourCanvas::Duple
+Item::item_to_canvas (ArdourCanvas::Duple const & d) const
+{
+       Item const * i = this;
+       Duple offset;
+
+       while (i) {
+               offset = offset.translate (i->position());
+               i = i->parent();
+       }
+
+       return d.translate (offset);
+}
+
+ArdourCanvas::Duple
+Item::canvas_to_item (ArdourCanvas::Duple const & d) const
+{
+       Item const * i = this;
+       Duple offset;
+
+       while (i) {
+               offset = offset.translate (-(i->position()));
+               i = i->parent();
+       }
+
+       return d.translate (offset);
+}
+
+void
+Item::item_to_canvas (Coord& x, Coord& y) const
+{
+       Duple d = item_to_canvas (Duple (x, y));
+               
+       x = d.x;
+       y = d.y;
+}
+
+void
+Item::canvas_to_item (Coord& x, Coord& y) const
+{
+       Duple d = canvas_to_item (Duple (x, y));
+
+       x = d.x;
+       y = d.y;
+}
+
 /** Set the position of this item in the parent's coordinates */
 void
 Item::set_position (Duple p)
@@ -75,6 +135,9 @@ Item::set_position (Duple p)
        boost::optional<ArdourCanvas::Rect> pre_change_parent_bounding_box;
 
        if (bbox) {
+               /* see the comment in Canvas::item_moved() to understand
+                * why we use the parent's bounding box here.
+                */
                pre_change_parent_bounding_box = item_to_parent (bbox.get());
        }
        
@@ -284,50 +347,6 @@ Item::get_data (string const & key) const
        return i->second;
 }
 
-void
-Item::item_to_canvas (Coord& x, Coord& y) const
-{
-       Duple d (x, y);
-       Item const * i = this;
-       
-       while (i) {
-               d = i->item_to_parent (d);
-               i = i->_parent;
-       }
-               
-       x = d.x;
-       y = d.y;
-}
-
-void
-Item::canvas_to_item (Coord& x, Coord& y) const
-{
-       Duple d (x, y);
-       Item const * i = this;
-
-       while (i) {
-               d = i->parent_to_item (d);
-               i = i->_parent;
-       }
-
-       x = d.x;
-       y = d.y;
-}
-
-ArdourCanvas::Rect
-Item::item_to_canvas (ArdourCanvas::Rect const & area) const
-{
-       ArdourCanvas::Rect r = area;
-       Item const * i = this;
-
-       while (i) {
-               r = i->item_to_parent (r);
-               i = i->parent ();
-       }
-
-       return r;
-}
-
 void
 Item::set_ignore_events (bool ignore)
 {
@@ -340,6 +359,7 @@ Item::dump (ostream& o) const
        boost::optional<ArdourCanvas::Rect> bb = bounding_box();
 
        o << _canvas->indent() << whatami() << ' ' << this;
+       o << " @ " << position();
        
 #ifdef CANVAS_DEBUG
        if (!name.empty()) {
@@ -349,6 +369,7 @@ Item::dump (ostream& o) const
 
        if (bb) {
                o << endl << _canvas->indent() << "\tbbox: " << bb.get();
+               o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb.get());
        } else {
                o << " bbox unset";
        }