diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index a508e1d080..558f24f31c 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -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 (); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 3f0098dcd0..faaae52ff6 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -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() { diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index d753d59551..1b9a820ae6 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -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 ()) { diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 30aab87d05..b717ef5464 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -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 diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 9fbf4533b4..42ff531a35 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -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; diff --git a/gtk2_ardour/tempo_lines.cc b/gtk2_ardour/tempo_lines.cc index 5cb059cbee..cd923d88a9 100644 --- a/gtk2_ardour/tempo_lines.cc +++ b/gtk2_ardour/tempo_lines.cc @@ -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; diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 433eee350d..a426656cf6 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -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); diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index b849894bf0..da34a73c21 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -100,18 +100,6 @@ Canvas::render (Rect const & area, Cairo::RefPtr 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 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 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 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)); } diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h index fc66754ed4..7f1321b260 100644 --- a/libs/canvas/canvas/item.h +++ b/libs/canvas/canvas/item.h @@ -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); diff --git a/libs/canvas/group.cc b/libs/canvas/group.cc index d12c13169e..34001bc255 100644 --- a/libs/canvas/group.cc +++ b/libs/canvas/group.cc @@ -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"; } diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc index 2c4ec893e7..75a5718271 100644 --- a/libs/canvas/item.cc +++ b/libs/canvas/item.cc @@ -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 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 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"; }