a few changes to fix region dragging, all related to coordinate system handling, which is now much simpler with the new canvas; more debugging output when asked for

This commit is contained in:
Paul Davis 2013-04-15 10:38:12 -04:00
parent cfe4bfb732
commit af4539f857
11 changed files with 117 additions and 97 deletions

View file

@ -1016,8 +1016,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool deferred_control_scroll (framepos_t); bool deferred_control_scroll (framepos_t);
sigc::connection control_scroll_connection; 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_background_group () const { return _background_group; }
ArdourCanvas::Group* get_trackview_group () const { return _trackview_group; } ArdourCanvas::Group* get_trackview_group () const { return _trackview_group; }
void tie_vertical_scrolling (); void tie_vertical_scrolling ();

View file

@ -33,6 +33,7 @@
#include "canvas/rectangle.h" #include "canvas/rectangle.h"
#include "canvas/pixbuf.h" #include "canvas/pixbuf.h"
#include "canvas/text.h" #include "canvas/text.h"
#include "canvas/debug.h"
#include "ardour_ui.h" #include "ardour_ui.h"
#include "editor.h" #include "editor.h"
@ -101,10 +102,14 @@ Editor::initialize_canvas ()
_background_group = new ArdourCanvas::Group (_track_canvas->root()); _background_group = new ArdourCanvas::Group (_track_canvas->root());
CANVAS_DEBUG_NAME (_background_group, "Canvas Background");
_master_group = new ArdourCanvas::Group (_track_canvas->root()); _master_group = new ArdourCanvas::Group (_track_canvas->root());
CANVAS_DEBUG_NAME (_master_group, "Canvas Master");
_trackview_group = new ArdourCanvas::Group (_master_group); _trackview_group = new ArdourCanvas::Group (_master_group);
CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
_region_motion_group = new ArdourCanvas::Group (_trackview_group); _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_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)); 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) */ /* Note whether we're fudging the autoscroll (see autoscroll_fudge_threshold) */
_autoscroll_fudging = (distance < 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_y = 0;
autoscroll_x = 0; autoscroll_x = 0;
@ -558,7 +563,7 @@ Editor::autoscroll_canvas ()
if (autoscroll_y_distance != 0) { if (autoscroll_y_distance != 0) {
if (autoscroll_y > 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) { } else if (autoscroll_y < 0) {
autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3; 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 */ 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 void
Editor::color_handler() Editor::color_handler()
{ {

View file

@ -670,12 +670,16 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
/* Reparent to a non scrolling group so that we can keep the /* Reparent to a non scrolling group so that we can keep the
region selection above all time axis views. region selection above all time axis views.
Reparenting means that we will have to move the region view 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->get_canvas_group()->reparent (_editor->_region_motion_group);
rv->fake_set_opaque (true); 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 /* If we have moved tracks, we'll fudge the layer delta so that the
@ -725,7 +729,6 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
/* Get the y coordinate of the top of the track that this region is now on */ /* Get the y coordinate of the top of the track that this region is now on */
tv->canvas_display()->item_to_canvas (x, y); 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 */ /* And adjust for the layer that it should be on */
StreamView* cv = tv->view (); StreamView* cv = tv->view ();

View file

@ -194,8 +194,7 @@ Editor::draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
tempo_lines = new TempoLines (*_track_canvas_viewport, time_line_group, physical_screen_height(get_window())); tempo_lines = new TempoLines (*_track_canvas_viewport, time_line_group, physical_screen_height(get_window()));
} }
// CAIROCANVAS tempo_lines->draw (begin, end, samples_per_pixel);
// tempo_lines->draw (begin, end, frames_per_unit);
} }
void void

View file

@ -380,7 +380,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
virtual Gtk::HBox& get_status_bar_packer() = 0; virtual Gtk::HBox& get_status_bar_packer() = 0;
#endif #endif
virtual gdouble get_trackview_group_vertical_offset () const = 0;
virtual ArdourCanvas::Group* get_trackview_group () const = 0; virtual ArdourCanvas::Group* get_trackview_group () const = 0;
virtual ArdourCanvas::Group* get_background_group () const = 0; virtual ArdourCanvas::Group* get_background_group () const = 0;

View 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 // Tempo map hasn't changed and we're entirely within a clean
// range, don't need to do anything. Yay. // range, don't need to do anything. Yay.
if (needed_left >= _clean_left && needed_right <= _clean_right) { if (needed_left >= _clean_left && needed_right <= _clean_right) {
// cout << endl << "*** LINE CACHE PERFECT HIT" << endl; // cerr << endl << "*** LINE CACHE PERFECT HIT" << endl;
return; return;
} }
//cout << endl << "*** LINE CACHE MISS" << endl; // cerr << endl << "*** LINE CACHE MISS" << endl;
bool invalidated = false; bool invalidated = false;
@ -169,7 +169,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
// Steal from the right // Steal from the right
if (left->first > needed_left && li != steal && steal->first > needed_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; double const x = steal->first;
line = steal->second; line = steal->second;
_lines.erase(steal); _lines.erase(steal);
@ -208,7 +208,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
// Create a new line // Create a new line
} else if (_lines.size() < needed || _lines.size() < MAX_CACHED_LINES) { } 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 we already have a line there ... don't sweat it */
if (_lines.find (xpos) == _lines.end()) { if (_lines.find (xpos) == _lines.end()) {
line = new ArdourCanvas::Line (_group); line = new ArdourCanvas::Line (_group);
@ -222,7 +222,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
// Steal from the left // Steal from the left
} else { } else {
//cout << "*** STEALING FROM LEFT" << endl; // cerr << "*** STEALING FROM LEFT" << endl;
if (_lines.find (xpos) == _lines.end()) { if (_lines.find (xpos) == _lines.end()) {
Lines::iterator steal = _lines.begin(); Lines::iterator steal = _lines.begin();
double const x = steal->first; double const x = steal->first;

View file

@ -373,7 +373,7 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev)
*/ */
int tx, ty; int tx, ty;
controls_ebox.translate_coordinates (*control_parent, ev->x, ev->y, 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.drags()->motion_handler ((GdkEvent *) ev, false);
_editor.maybe_autoscroll (false, true, false, ev->y_root < _resize_drag_start); _editor.maybe_autoscroll (false, true, false, ev->y_root < _resize_drag_start);

View file

@ -100,18 +100,6 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
// checkpoint ("render", "-> render"); // checkpoint ("render", "-> render");
render_count = 0; 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 (); context->save ();
/* clip to the requested area */ /* clip to the requested area */
@ -143,6 +131,17 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
context->restore (); 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"); // checkpoint ("render", "<- render");
} }
@ -225,10 +224,15 @@ void
Canvas::item_moved (Item* item, boost::optional<Rect> pre_change_parent_bounding_box) Canvas::item_moved (Item* item, boost::optional<Rect> pre_change_parent_bounding_box)
{ {
if (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 /* request a redraw of where the item used to be. The box has
parent's coordinates here as item bounding boxes do not change * to be in parent coordinate space since the bounding box of
when the item moves. * 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 ()); 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 void
Canvas::queue_draw_item_area (Item* item, Rect area) 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 */ /** @return An XML description of the canvas and its objects */
@ -554,6 +560,7 @@ void
GtkCanvas::request_redraw (Rect const & request) GtkCanvas::request_redraw (Rect const & request)
{ {
Rect area = canvas_to_window (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)); queue_draw_area (floor (area.x0), floor (area.y0), ceil (area.x1) - floor (area.x0), ceil (area.y1) - floor (area.y0));
} }

View file

@ -108,9 +108,12 @@ public:
/* XXX: it's a pity these aren't the same form as item_to_parent etc., /* 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. 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; void item_to_canvas (Coord &, Coord &) const;
Rect item_to_canvas (Rect const &) const; Rect item_to_canvas (Rect const &) const;
Duple item_to_canvas (Duple const &) const;
void raise_to_top (); void raise_to_top ();
void raise (int); void raise (int);

View file

@ -278,6 +278,7 @@ Group::dump (ostream& o) const
{ {
o << _canvas->indent(); o << _canvas->indent();
o << "Group " << this << " [" << name << ']'; o << "Group " << this << " [" << name << ']';
o << " @ " << position();
o << " Items: " << _items.size(); o << " Items: " << _items.size();
o << " Visible ? " << _visible; o << " Visible ? " << _visible;
@ -285,6 +286,7 @@ Group::dump (ostream& o) const
if (bb) { if (bb) {
o << endl << _canvas->indent() << " bbox: " << bb.get(); o << endl << _canvas->indent() << " bbox: " << bb.get();
o << endl << _canvas->indent() << " CANVAS bbox: " << item_to_canvas (bb.get());
} else { } else {
o << " bbox unset"; o << " bbox unset";
} }

View file

@ -67,6 +67,66 @@ Item::item_to_parent (ArdourCanvas::Rect const & r) const
return r.translate (_position); 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 */ /** Set the position of this item in the parent's coordinates */
void void
Item::set_position (Duple p) Item::set_position (Duple p)
@ -75,6 +135,9 @@ Item::set_position (Duple p)
boost::optional<ArdourCanvas::Rect> pre_change_parent_bounding_box; boost::optional<ArdourCanvas::Rect> pre_change_parent_bounding_box;
if (bbox) { 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()); pre_change_parent_bounding_box = item_to_parent (bbox.get());
} }
@ -284,50 +347,6 @@ Item::get_data (string const & key) const
return i->second; 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 void
Item::set_ignore_events (bool ignore) Item::set_ignore_events (bool ignore)
{ {
@ -340,6 +359,7 @@ Item::dump (ostream& o) const
boost::optional<ArdourCanvas::Rect> bb = bounding_box(); boost::optional<ArdourCanvas::Rect> bb = bounding_box();
o << _canvas->indent() << whatami() << ' ' << this; o << _canvas->indent() << whatami() << ' ' << this;
o << " @ " << position();
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (!name.empty()) { if (!name.empty()) {
@ -349,6 +369,7 @@ Item::dump (ostream& o) const
if (bb) { if (bb) {
o << endl << _canvas->indent() << "\tbbox: " << bb.get(); o << endl << _canvas->indent() << "\tbbox: " << bb.get();
o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb.get());
} else { } else {
o << " bbox unset"; o << " bbox unset";
} }