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,10 +65,8 @@ Editor::initialize_canvas ()
{
_track_canvas_viewport = new ArdourCanvas::GtkCanvasViewport (horizontal_adjustment, vertical_adjustment);
_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);
/* on the bottom, an image */
@ -100,7 +98,15 @@ Editor::initialize_canvas ()
CANVAS_DEBUG_NAME (time_line_group, "time line group");
_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");
/* 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);
CANVAS_DEBUG_NAME (_region_motion_group, "Canvas Region Motion");

View File

@ -1465,16 +1465,23 @@ Editor::update_punch_range_view ()
Location* tpl;
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()) {
transport_punch_range_rect->set_x0 (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));
pixel_start = sample_to_pixel (tpl->start());
} else {
transport_punch_range_rect->set_x0 (0);
transport_punch_range_rect->set_x1 (_session->config.get_punch_out() ? sample_to_pixel (tpl->end()) : v.width ());
pixel_start = 0;
}
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();
} else {

View File

@ -65,7 +65,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
const ARDOUR::TempoMap::BBTPointList::const_iterator& end)
{
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;
uint32_t beats = 0;

View File

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

View File

@ -51,7 +51,9 @@ public:
void raise_child (Item *, int);
void lower_child_to_bottom (Item *);
void child_changed ();
void scroll_to (Duple const& d);
void add_items_at_point (Duple, std::vector<Item const *> &) const;
void dump (std::ostream&) const;

View File

@ -112,6 +112,17 @@ public:
void set_y_position (Coord);
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 */
Duple position () const {
return _position;
@ -125,21 +136,18 @@ public:
Rect item_to_parent (Rect const &) const;
Duple parent_to_item (Duple 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.
*/
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;
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 window_to_item (Duple const&) const;
Rect item_to_window (Rect const&) const;
Rect window_to_item (Rect const&) const;
void raise_to_top ();
void raise (int);
void lower_to_bottom ();
@ -240,6 +248,8 @@ private:
void init ();
bool _ignore_events;
ScrollSensitivity _scroll_sensitivity;
Duple _scroll_offset;
};
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;
}
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
Group::compute_bounding_box () const
{

View File

@ -35,6 +35,7 @@ using namespace ArdourCanvas;
Item::Item (Canvas* canvas)
: _canvas (canvas)
, _parent (0)
, _scroll_sensitivity (ScrollSensitivity (0))
{
init ();
}
@ -42,6 +43,7 @@ Item::Item (Canvas* canvas)
Item::Item (Group* parent)
: _canvas (parent->canvas ())
, _parent (parent)
, _scroll_sensitivity (ScrollSensitivity (0))
{
init ();
}
@ -50,6 +52,7 @@ Item::Item (Group* parent, Duple position)
: _canvas (parent->canvas())
, _parent (parent)
, _position (position)
, _scroll_sensitivity (ScrollSensitivity (0))
{
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
Item::item_to_parent (ArdourCanvas::Rect const & r) const
{
@ -162,19 +183,57 @@ Item::canvas_to_item (Coord& x, Coord& y) const
Duple
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
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
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 */
@ -517,7 +576,7 @@ Item::dump (ostream& o) const
boost::optional<ArdourCanvas::Rect> bb = bounding_box();
o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible;
o << " @ " << position();
o << " @ " << position() << " scrolled-to " << _scroll_offset;
#ifdef CANVAS_DEBUG
if (!name.empty()) {

View File

@ -180,7 +180,7 @@ Line::covers (Duple const & point) const
double t;
Duple a (_points[0]);
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

View File

@ -59,7 +59,7 @@ PolyLine::covers (Duple const & point) const
/* 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) {