13
0

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);
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 ();

View 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()
{

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
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 ()) {

View 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

View 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;

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
// 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;

View 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);

View 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));
}

View 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);

View 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";
}

View 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";
}