initial redesign of canvas scrolling to facilitate independent x- and y-axis scrolling of specific groups within the canvas.

This commit should cause no change in behaviour, but contains all the code and changes necessary
for the next step
This commit is contained in:
Paul Davis 2014-05-18 12:22:23 -04:00
parent ee6c483d18
commit 97109672c7
11 changed files with 144 additions and 38 deletions

View file

@ -65,9 +65,7 @@ Editor::initialize_canvas ()
{ {
_track_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, vertical_adjustment); _track_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, vertical_adjustment);
_track_canvas = _track_canvas_viewport->canvas (); _track_canvas = _track_canvas_viewport->canvas ();
//_track_canvas->set_global_scroll (false);
_time_bars_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, unused_adjustment);
_time_bars_canvas = _time_bars_canvas_viewport->canvas ();
_verbose_cursor = new VerboseCursor (this); _verbose_cursor = new VerboseCursor (this);
@ -100,7 +98,15 @@ Editor::initialize_canvas ()
CANVAS_DEBUG_NAME (time_line_group, "time line group"); CANVAS_DEBUG_NAME (time_line_group, "time line group");
_trackview_group = new ArdourCanvas::Group (_track_canvas->root()); _trackview_group = new ArdourCanvas::Group (_track_canvas->root());
//_trackview_group->set_scroll_sensitivity (ArdourCanvas::Group::ScrollSensitivity (ArdourCanvas::Group::ScrollsVertically|ArdourCanvas::Group::ScrollsHorizontally));
CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews"); CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
/* TIME BAR CANVAS */
_time_bars_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, unused_adjustment);
_time_bars_canvas = _time_bars_canvas_viewport->canvas ();
_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"); CANVAS_DEBUG_NAME (_region_motion_group, "Canvas Region Motion");

View file

@ -1465,16 +1465,23 @@ Editor::update_punch_range_view ()
Location* tpl; Location* tpl;
if ((_session->config.get_punch_in() || _session->config.get_punch_out()) && ((tpl = transport_punch_location()) != 0)) { if ((_session->config.get_punch_in() || _session->config.get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
ArdourCanvas::Rect const v = _track_canvas->visible_area ();
double pixel_start;
double pixel_end;
if (_session->config.get_punch_in()) { if (_session->config.get_punch_in()) {
transport_punch_range_rect->set_x0 (sample_to_pixel (tpl->start())); pixel_start = sample_to_pixel (tpl->start());
transport_punch_range_rect->set_x1 (_session->config.get_punch_out() ? sample_to_pixel (tpl->end()) : sample_to_pixel (max_framepos));
} else { } else {
transport_punch_range_rect->set_x0 (0); pixel_start = 0;
transport_punch_range_rect->set_x1 (_session->config.get_punch_out() ? sample_to_pixel (tpl->end()) : v.width ()); }
if (_session->config.get_punch_out()) {
pixel_end = sample_to_pixel (tpl->end());
} else {
pixel_end = sample_to_pixel (max_framepos);
} }
transport_punch_range_rect->set_x0 (pixel_start);
transport_punch_range_rect->set_x1 (pixel_end);
transport_punch_range_rect->show(); transport_punch_range_rect->show();
} else { } else {

View file

@ -65,7 +65,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
const ARDOUR::TempoMap::BBTPointList::const_iterator& end) const ARDOUR::TempoMap::BBTPointList::const_iterator& end)
{ {
ARDOUR::TempoMap::BBTPointList::const_iterator i; ARDOUR::TempoMap::BBTPointList::const_iterator i;
ArdourCanvas::Rect const visible = _canvas.visible_area (); ArdourCanvas::Rect const visible = _group->window_to_item (_canvas.visible_area ());
double beat_density; double beat_density;
uint32_t beats = 0; uint32_t beats = 0;

View file

@ -40,8 +40,7 @@ using namespace ArdourCanvas;
/** Construct a new Canvas */ /** Construct a new Canvas */
Canvas::Canvas () Canvas::Canvas ()
: _root (this) : _root (this)
, _scroll_offset_x (0) , _global_scroll (true)
, _scroll_offset_y (0)
{ {
set_epoch (); set_epoch ();
} }
@ -49,12 +48,23 @@ Canvas::Canvas ()
void void
Canvas::scroll_to (Coord x, Coord y) Canvas::scroll_to (Coord x, Coord y)
{ {
_scroll_offset_x = x; Duple d (x, y);
_scroll_offset_y = y;
if (_global_scroll) {
_scroll_offset = d;
}
//_root.scroll_to (d);
pick_current_item (0); // no current mouse position pick_current_item (0); // no current mouse position
} }
void
Canvas::set_global_scroll (bool yn)
{
_global_scroll = yn;
}
void void
Canvas::zoomed () Canvas::zoomed ()
{ {
@ -71,9 +81,9 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
cerr << this << " RENDER: " << area << endl; cerr << this << " RENDER: " << area << endl;
//cerr << "CANVAS @ " << this << endl; cerr << "CANVAS @ " << this << endl;
//dump (cerr); dump (cerr);
//cerr << "-------------------------\n"; cerr << "-------------------------\n";
} }
#endif #endif
@ -189,13 +199,13 @@ Canvas::item_changed (Item* item, boost::optional<Rect> pre_change_bounding_box)
Duple Duple
Canvas::window_to_canvas (Duple const & d) const Canvas::window_to_canvas (Duple const & d) const
{ {
return d.translate (Duple (_scroll_offset_x, _scroll_offset_y)); return d.translate (Duple (_scroll_offset.x, _scroll_offset.y));
} }
Duple Duple
Canvas::canvas_to_window (Duple const & d, bool rounded) const 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 (Duple (-_scroll_offset.x, -_scroll_offset.y));
/* Note that this intentionally almost always returns integer coordinates */ /* Note that this intentionally almost always returns integer coordinates */
if (rounded) { if (rounded) {
@ -209,13 +219,13 @@ Canvas::canvas_to_window (Duple const & d, bool rounded) const
Rect Rect
Canvas::window_to_canvas (Rect const & r) const Canvas::window_to_canvas (Rect const & r) const
{ {
return r.translate (Duple (_scroll_offset_x, _scroll_offset_y)); return r.translate (Duple (_scroll_offset.x, _scroll_offset.y));
} }
Rect Rect
Canvas::canvas_to_window (Rect const & r, bool rounded) const Canvas::canvas_to_window (Rect const & r, bool rounded) const
{ {
Rect wr = r.translate (Duple (-_scroll_offset_x, -_scroll_offset_y)); Rect wr = r.translate (Duple (-_scroll_offset.x, -_scroll_offset.y));
/* Note that this intentionally almost always returns integer coordinates */ /* Note that this intentionally almost always returns integer coordinates */
@ -802,8 +812,8 @@ GtkCanvas::unfocus (Item* item)
Rect Rect
GtkCanvas::visible_area () const GtkCanvas::visible_area () const
{ {
Distance const xo = _scroll_offset_x; Distance const xo = _scroll_offset.x;
Distance const yo = _scroll_offset_y; Distance const yo = _scroll_offset.y;
return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ()); return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ());
} }

View file

@ -108,6 +108,8 @@ public:
} }
void scroll_to (Coord x, Coord y); void scroll_to (Coord x, Coord y);
void set_global_scroll (bool);
virtual Rect visible_area () const = 0; virtual Rect visible_area () const = 0;
void zoomed(); void zoomed();
@ -122,8 +124,8 @@ protected:
/** our root group */ /** our root group */
RootGroup _root; RootGroup _root;
Coord _scroll_offset_x; Duple _scroll_offset;
Coord _scroll_offset_y; bool _global_scroll;
virtual void pick_current_item (int state) = 0; virtual void pick_current_item (int state) = 0;
virtual void pick_current_item (Duple const &, int state) = 0; virtual void pick_current_item (Duple const &, int state) = 0;

View file

@ -52,6 +52,8 @@ public:
void lower_child_to_bottom (Item *); void lower_child_to_bottom (Item *);
void child_changed (); void child_changed ();
void scroll_to (Duple const& d);
void add_items_at_point (Duple, std::vector<Item const *> &) const; void add_items_at_point (Duple, std::vector<Item const *> &) const;
void dump (std::ostream&) const; void dump (std::ostream&) const;

View file

@ -112,6 +112,17 @@ public:
void set_y_position (Coord); void set_y_position (Coord);
void move (Duple); void move (Duple);
enum ScrollSensitivity {
ScrollsVertically = 0x1,
ScrollsHorizontally = 0x2
};
void set_scroll_sensitivity (ScrollSensitivity s);
ScrollSensitivity scroll_sensitivity () const { return _scroll_sensitivity; }
virtual void scroll_to (Duple const& d);
Duple scroll_offset() const { return _scroll_offset; }
/** @return Position of this item in the parent's coordinates */ /** @return Position of this item in the parent's coordinates */
Duple position () const { Duple position () const {
return _position; return _position;
@ -125,20 +136,17 @@ public:
Rect item_to_parent (Rect const &) const; Rect item_to_parent (Rect const &) const;
Duple parent_to_item (Duple const &) const; Duple parent_to_item (Duple const &) const;
Rect parent_to_item (Rect const &) const; Rect parent_to_item (Rect const &) const;
/* XXX: it's a pity these aren't the same form as item_to_parent etc.,
/* XXX: it's a pity these two 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 canvas_to_item (Rect const &) const;
Duple item_to_canvas (Duple const &) const;
Duple item_to_window (Duple const&, bool rounded = true) const; Duple item_to_window (Duple const&, bool rounded = true) const;
Duple window_to_item (Duple const&) const; Duple window_to_item (Duple const&) const;
Rect item_to_window (Rect const&) const; Rect item_to_window (Rect const&) const;
Rect window_to_item (Rect const&) const;
void raise_to_top (); void raise_to_top ();
void raise (int); void raise (int);
@ -240,6 +248,8 @@ private:
void init (); void init ();
bool _ignore_events; bool _ignore_events;
ScrollSensitivity _scroll_sensitivity;
Duple _scroll_offset;
}; };
extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&); extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);

View file

@ -147,6 +147,16 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
--render_depth; --render_depth;
} }
void
Group::scroll_to (Duple const& d)
{
Item::scroll_to (d);
for (list<Item*>::iterator i = _items.begin(); i != _items.end(); ) {
(*i)->scroll_to (d);
}
}
void void
Group::compute_bounding_box () const Group::compute_bounding_box () const
{ {

View file

@ -35,6 +35,7 @@ using namespace ArdourCanvas;
Item::Item (Canvas* canvas) Item::Item (Canvas* canvas)
: _canvas (canvas) : _canvas (canvas)
, _parent (0) , _parent (0)
, _scroll_sensitivity (ScrollSensitivity (0))
{ {
init (); init ();
} }
@ -42,6 +43,7 @@ Item::Item (Canvas* canvas)
Item::Item (Group* parent) Item::Item (Group* parent)
: _canvas (parent->canvas ()) : _canvas (parent->canvas ())
, _parent (parent) , _parent (parent)
, _scroll_sensitivity (ScrollSensitivity (0))
{ {
init (); init ();
} }
@ -50,6 +52,7 @@ Item::Item (Group* parent, Duple position)
: _canvas (parent->canvas()) : _canvas (parent->canvas())
, _parent (parent) , _parent (parent)
, _position (position) , _position (position)
, _scroll_sensitivity (ScrollSensitivity (0))
{ {
init (); init ();
} }
@ -79,6 +82,24 @@ Item::~Item ()
} }
} }
void
Item::scroll_to (Duple const& d)
{
if (_scroll_sensitivity & ScrollsVertically) {
_scroll_offset.y = d.y;
}
if (_scroll_sensitivity & ScrollsHorizontally) {
_scroll_offset.x = d.x;
}
}
void
Item::set_scroll_sensitivity (ScrollSensitivity s)
{
_scroll_sensitivity = s;
}
ArdourCanvas::Rect ArdourCanvas::Rect
Item::item_to_parent (ArdourCanvas::Rect const & r) const Item::item_to_parent (ArdourCanvas::Rect const & r) const
{ {
@ -162,19 +183,57 @@ Item::canvas_to_item (Coord& x, Coord& y) const
Duple Duple
Item::item_to_window (ArdourCanvas::Duple const & d, bool rounded) const Item::item_to_window (ArdourCanvas::Duple const & d, bool rounded) const
{ {
return _canvas->canvas_to_window (item_to_canvas (d), rounded); Item const * i = this;
Duple offset;
while (i) {
offset = offset.translate (i->scroll_offset());
i = i->parent();
}
return _canvas->canvas_to_window (d.translate (offset), rounded);
} }
Duple Duple
Item::window_to_item (ArdourCanvas::Duple const & d) const Item::window_to_item (ArdourCanvas::Duple const & d) const
{ {
return _canvas->window_to_canvas (canvas_to_item (d)); Item const * i = this;
Duple offset;
while (i) {
offset = offset.translate (-i->scroll_offset());
i = i->parent();
}
return _canvas->window_to_canvas (d.translate (offset));
} }
ArdourCanvas::Rect ArdourCanvas::Rect
Item::item_to_window (ArdourCanvas::Rect const & r) const Item::item_to_window (ArdourCanvas::Rect const & r) const
{ {
return _canvas->canvas_to_window (item_to_canvas (r)); Item const * i = this;
Duple offset;
while (i) {
offset = offset.translate (i->scroll_offset());
i = i->parent();
}
return _canvas->canvas_to_window (item_to_canvas (r.translate (offset)));
}
ArdourCanvas::Rect
Item::window_to_item (ArdourCanvas::Rect const & r) const
{
Item const * i = this;
Duple offset;
while (i) {
offset = offset.translate (-i->scroll_offset());
i = i->parent();
}
return canvas_to_item (_canvas->window_to_canvas (r).translate (offset));
} }
/** Set the position of this item in the parent's coordinates */ /** Set the position of this item in the parent's coordinates */
@ -517,7 +576,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 << " Visible ? " << _visible; o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible;
o << " @ " << position(); o << " @ " << position() << " scrolled-to " << _scroll_offset;
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (!name.empty()) { if (!name.empty()) {

View file

@ -180,7 +180,7 @@ Line::covers (Duple const & point) const
double t; double t;
Duple a (_points[0]); Duple a (_points[0]);
Duple b (_points[1]); Duple b (_points[1]);
const Rect visible (_canvas->visible_area()); const Rect visible (window_to_item (_canvas->visible_area()));
/* /*
Clamp the line endpoints to the visible area of the canvas. If we do Clamp the line endpoints to the visible area of the canvas. If we do

View file

@ -59,7 +59,7 @@ PolyLine::covers (Duple const & point) const
/* repeat for each line segment */ /* repeat for each line segment */
const Rect visible (_canvas->visible_area()); const Rect visible (window_to_item (_canvas->visible_area()));
for (i = 1, j = 0; i < npoints; ++i, ++j) { for (i = 1, j = 0; i < npoints; ++i, ++j) {