summaryrefslogtreecommitdiff
path: root/libs/canvas
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2014-05-21 10:25:28 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2014-06-03 16:10:27 -0400
commitc9f890bd7c3377d86030e98f002d85acd66f0997 (patch)
tree990b4006f30e4f5c08caf75d54c6bb8509a59e86 /libs/canvas
parenta5511818422c13ebc6f98cccf0996f821985cc67 (diff)
avoid recursing through the entire canvas when scrolling - only scroll explicitly identified ScrollGroups
Diffstat (limited to 'libs/canvas')
-rw-r--r--libs/canvas/canvas.cc29
-rw-r--r--libs/canvas/canvas/canvas.h6
2 files changed, 26 insertions, 9 deletions
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index aad614d906..f29bdba72c 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -33,6 +33,7 @@
#include "canvas/canvas.h"
#include "canvas/debug.h"
#include "canvas/line.h"
+#include "canvas/scroll_group.h"
using namespace std;
using namespace ArdourCanvas;
@@ -40,7 +41,6 @@ using namespace ArdourCanvas;
/** Construct a new Canvas */
Canvas::Canvas ()
: _root (this)
- , _global_scroll (true)
{
set_epoch ();
}
@@ -48,19 +48,29 @@ Canvas::Canvas ()
void
Canvas::scroll_to (Coord x, Coord y)
{
- Duple d (x, y);
-
- _scroll_offset = d;
+ _scroll_offset = Duple (x, y);
+
+ /* We do things this way because we do not want to recurse through
+ the canvas for every scroll. In the presence of large MIDI
+ tracks this means traversing item lists that include
+ thousands of items (notes).
- _root.scroll_to (d);
+ This design limits us to moving only those items (groups, typically)
+ that should move in certain ways as we scroll. In other terms, it
+ becomes O(1) rather than O(N).
+ */
+
+ for (list<ScrollGroup*>::iterator i = scrollers.begin(); i != scrollers.end(); ++i) {
+ (*i)->scroll_to (_scroll_offset);
+ }
pick_current_item (0); // no current mouse position
}
void
-Canvas::set_global_scroll (bool yn)
+Canvas::add_scroller (ScrollGroup& i)
{
- _global_scroll = yn;
+ scrollers.push_back (&i);
}
void
@@ -602,6 +612,11 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
_focused_item = 0;
}
+ ScrollGroup* sg = dynamic_cast<ScrollGroup*>(item);
+ if (sg) {
+ scrollers.remove (sg);
+ }
+
if (_current_item == item) {
/* no need to send a leave event to this item, since it is going away
*/
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
index 1e2a567d58..3f7d6fd519 100644
--- a/libs/canvas/canvas/canvas.h
+++ b/libs/canvas/canvas/canvas.h
@@ -43,6 +43,7 @@ namespace ArdourCanvas
class Rect;
class Group;
+class ScrollGroup;
/** The base class for our different types of canvas.
*
@@ -108,7 +109,7 @@ public:
}
void scroll_to (Coord x, Coord y);
- void set_global_scroll (bool);
+ void add_scroller (ScrollGroup& i);
virtual Rect visible_area () const = 0;
@@ -125,10 +126,11 @@ protected:
RootGroup _root;
Duple _scroll_offset;
- bool _global_scroll;
virtual void pick_current_item (int state) = 0;
virtual void pick_current_item (Duple const &, int state) = 0;
+
+ std::list<ScrollGroup*> scrollers;
};
/** A canvas which renders onto a GTK EventBox */