summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2014-05-20 23:08:15 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2014-06-03 16:10:27 -0400
commit6019f06bdf919e1d95dd0912116cdec0834af8db (patch)
treebe8d2e41e692c2e8a572f531b546efde67b1503f /libs
parentfc9e6651dd804672822e06cbd4092c043dc8406d (diff)
different approach to independent scrolling, involving ArdourCanvas::ScrollGroup
The idea now is that a scroll group item can be added to the canvas which will causes its children to scroll in either or both directions (horizontal or vertical). There are few complications: the position() of the ScrollGroup is ambiguous depending on whether you want it with scroll taken into account or not, so Item::canvas_position() was added, which defaults to the same value as Item::position() but is overridden by ScrollGroup to return the position independent of scrolling. This method is used when translating between item/canvas/window coordinate systems. Note that the basic idea is that we MOVE the scroll group when a scroll happens. This mirrors what happens in the GnomeCanvas, where Nick Mainsbridge came up with a great idea that allowed unification of the time bar and track canvases.
Diffstat (limited to 'libs')
-rw-r--r--libs/canvas/canvas.cc17
-rw-r--r--libs/canvas/canvas/item.h17
-rw-r--r--libs/canvas/canvas/scroll_group.h47
-rw-r--r--libs/canvas/canvas/wave_view.h2
-rw-r--r--libs/canvas/group.cc10
-rw-r--r--libs/canvas/item.cc61
-rw-r--r--libs/canvas/scroll_group.cc63
-rw-r--r--libs/canvas/wave_view.cc26
-rw-r--r--libs/canvas/wscript1
9 files changed, 152 insertions, 92 deletions
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index 8d4c1b8858..aad614d906 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -50,11 +50,9 @@ Canvas::scroll_to (Coord x, Coord y)
{
Duple d (x, y);
- if (_global_scroll) {
- _scroll_offset = d;
- }
-
- //_root.scroll_to (d);
+ _scroll_offset = d;
+
+ _root.scroll_to (d);
pick_current_item (0); // no current mouse position
}
@@ -81,9 +79,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
@@ -208,13 +206,14 @@ Canvas::canvas_to_window (Duple const & d, bool rounded) const
Duple wd = d.translate (Duple (-_scroll_offset.x, -_scroll_offset.y));
/* Note that this intentionally almost always returns integer coordinates */
+
if (rounded) {
wd.x = round (wd.x);
wd.y = round (wd.y);
}
return wd;
-}
+}
Rect
Canvas::window_to_canvas (Rect const & r) const
diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h
index 429df33894..487efae4d0 100644
--- a/libs/canvas/canvas/item.h
+++ b/libs/canvas/canvas/item.h
@@ -112,22 +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; }
+ virtual void scroll_to (Duple const&) {}
/** @return Position of this item in the parent's coordinates */
Duple position () const {
return _position;
}
+ virtual Duple canvas_position () const {
+ return _position;
+ }
+
boost::optional<Rect> bounding_box () const;
Coord height() const;
Coord width() const;
@@ -248,8 +243,6 @@ private:
void init ();
bool _ignore_events;
- ScrollSensitivity _scroll_sensitivity;
- Duple _scroll_offset;
};
extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);
diff --git a/libs/canvas/canvas/scroll_group.h b/libs/canvas/canvas/scroll_group.h
new file mode 100644
index 0000000000..c2b26bf9d9
--- /dev/null
+++ b/libs/canvas/canvas/scroll_group.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2014 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __CANVAS_SCROLL_GROUP_H__
+#define __CANVAS_SCROLL_GROUP_H__
+
+#include "canvas/group.h"
+
+namespace ArdourCanvas {
+
+class LIBCANVAS_API ScrollGroup : public Group
+{
+ public:
+ enum ScrollSensitivity {
+ ScrollsVertically = 0x1,
+ ScrollsHorizontally = 0x2
+ };
+
+ explicit ScrollGroup (Group *, ScrollSensitivity);
+ explicit ScrollGroup (Group *, Duple, ScrollSensitivity);
+
+ void scroll_to (Duple const& d);
+ Duple canvas_position() const;
+
+ private:
+ ScrollSensitivity _scroll_sensitivity;
+ Duple _scroll_offset;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/wave_view.h b/libs/canvas/canvas/wave_view.h
index 307528c685..0ddffca180 100644
--- a/libs/canvas/canvas/wave_view.h
+++ b/libs/canvas/canvas/wave_view.h
@@ -173,7 +173,7 @@ private:
void handle_clip_level_change ();
void ensure_cache (ARDOUR::framepos_t sample_start, ARDOUR::framepos_t sample_end) const;
- ArdourCanvas::Coord position (double) const;
+ ArdourCanvas::Coord y_extent (double) const;
void draw_image (ARDOUR::PeakData*, int npeaks) const;
};
diff --git a/libs/canvas/group.cc b/libs/canvas/group.cc
index b6df3dfee6..509be0b51a 100644
--- a/libs/canvas/group.cc
+++ b/libs/canvas/group.cc
@@ -117,7 +117,9 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
<< (*i)->whatami()
<< ' '
<< (*i)->name
- << " item = "
+ << " item "
+ << item_bbox.get()
+ << " window = "
<< item
<< " intersect = "
<< draw
@@ -136,8 +138,8 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
#ifdef CANVAS_DEBUG
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
- cerr << string_compose ("%1skip render of %2 %3, no intersection\n", _canvas->render_indent(), (*i)->whatami(),
- (*i)->name);
+ cerr << string_compose ("%1skip render of %2 %3, no intersection between %4 and %5\n", _canvas->render_indent(), (*i)->whatami(),
+ (*i)->name, item, area);
}
#endif
@@ -152,7 +154,7 @@ Group::scroll_to (Duple const& d)
{
Item::scroll_to (d);
- for (list<Item*>::iterator i = _items.begin(); i != _items.end(); ) {
+ for (list<Item*>::iterator i = _items.begin(); i != _items.end(); ++i) {
(*i)->scroll_to (d);
}
}
diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc
index 7a55e9604f..c6652f9d3a 100644
--- a/libs/canvas/item.cc
+++ b/libs/canvas/item.cc
@@ -35,7 +35,6 @@ using namespace ArdourCanvas;
Item::Item (Canvas* canvas)
: _canvas (canvas)
, _parent (0)
- , _scroll_sensitivity (ScrollSensitivity (0))
{
init ();
}
@@ -43,7 +42,6 @@ Item::Item (Canvas* canvas)
Item::Item (Group* parent)
: _canvas (parent->canvas ())
, _parent (parent)
- , _scroll_sensitivity (ScrollSensitivity (0))
{
init ();
}
@@ -52,7 +50,6 @@ Item::Item (Group* parent, Duple position)
: _canvas (parent->canvas())
, _parent (parent)
, _position (position)
- , _scroll_sensitivity (ScrollSensitivity (0))
{
init ();
}
@@ -82,24 +79,6 @@ 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
{
@@ -113,7 +92,7 @@ Item::item_to_canvas (ArdourCanvas::Rect const & r) const
Duple offset;
while (i) {
- offset = offset.translate (i->position());
+ offset = offset.translate (i->canvas_position());
i = i->parent();
}
@@ -127,7 +106,7 @@ Item::item_to_canvas (ArdourCanvas::Duple const & d) const
Duple offset;
while (i) {
- offset = offset.translate (i->position());
+ offset = offset.translate (i->canvas_position());
i = i->parent();
}
@@ -141,7 +120,7 @@ Item::canvas_to_item (ArdourCanvas::Duple const & d) const
Duple offset;
while (i) {
- offset = offset.translate (-(i->position()));
+ offset = offset.translate (-(i->canvas_position()));
i = i->parent();
}
@@ -155,7 +134,7 @@ Item::canvas_to_item (ArdourCanvas::Rect const & d) const
Duple offset;
while (i) {
- offset = offset.translate (-(i->position()));
+ offset = offset.translate (-(i->canvas_position()));
i = i->parent();
}
@@ -197,43 +176,19 @@ Item::item_to_window (ArdourCanvas::Duple const & d, bool rounded) const
Duple
Item::window_to_item (ArdourCanvas::Duple const & d) const
{
- 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));
+ return canvas_to_item (_canvas->window_to_canvas (d));
}
ArdourCanvas::Rect
Item::item_to_window (ArdourCanvas::Rect const & r) const
{
- 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)));
+ return _canvas->canvas_to_window (item_to_canvas (r));
}
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));
+ return canvas_to_item (_canvas->window_to_canvas (r));
}
/** Set the position of this item in the parent's coordinates */
@@ -576,7 +531,7 @@ Item::dump (ostream& o) const
boost::optional<ArdourCanvas::Rect> bb = bounding_box();
o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible;
- o << " @ " << position() << " scrolled-to " << _scroll_offset;
+ o << " @ " << position();
#ifdef CANVAS_DEBUG
if (!name.empty()) {
diff --git a/libs/canvas/scroll_group.cc b/libs/canvas/scroll_group.cc
new file mode 100644
index 0000000000..bda6911ca7
--- /dev/null
+++ b/libs/canvas/scroll_group.cc
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2014 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <iostream>
+#include "canvas/scroll_group.h"
+
+using namespace std;
+using namespace ArdourCanvas;
+
+ScrollGroup::ScrollGroup (Group* parent, ScrollSensitivity s)
+ : Group (parent)
+ , _scroll_sensitivity (s)
+{
+}
+
+ScrollGroup::ScrollGroup (Group* parent, Duple position, ScrollSensitivity s)
+ : Group (parent, position)
+ , _scroll_sensitivity (s)
+{
+}
+
+void
+ScrollGroup::scroll_to (Duple const& d)
+{
+ Duple base_pos (position().translate (_scroll_offset));
+
+ if (_scroll_sensitivity & ScrollsHorizontally) {
+ base_pos.x -= d.x;
+ _scroll_offset.x = d.x;
+ }
+
+ if (_scroll_sensitivity & ScrollsVertically) {
+ base_pos.y -= d.y;
+ _scroll_offset.y = d.y;
+ }
+
+ set_position (base_pos);
+}
+
+Duple
+ScrollGroup::canvas_position() const
+{
+ /* return the normal "base" position of this item
+ rather its position as affected by any scroll
+ offset.
+ */
+ return _position.translate (_scroll_offset);
+}
diff --git a/libs/canvas/wave_view.cc b/libs/canvas/wave_view.cc
index fa2c617d7b..3de5af1c51 100644
--- a/libs/canvas/wave_view.cc
+++ b/libs/canvas/wave_view.cc
@@ -219,7 +219,7 @@ WaveView::draw_image (PeakData* _peaks, int n_peaks) const
if (_logscaled) {
for (int i = 0; i < n_peaks; ++i) {
tips[i].bot = height();
- tips[i].top = position (alt_log_meter (fast_coefficient_to_dB (max (fabs (_peaks[i].max), fabs (_peaks[i].min)))));
+ tips[i].top = y_extent (alt_log_meter (fast_coefficient_to_dB (max (fabs (_peaks[i].max), fabs (_peaks[i].min)))));
if (fabs (_peaks[i].max) >= clip_level) {
tips[i].clip_max = true;
@@ -231,7 +231,7 @@ WaveView::draw_image (PeakData* _peaks, int n_peaks) const
}
} else {for (int i = 0; i < n_peaks; ++i) {
tips[i].bot = height();
- tips[i].top = position (max (fabs (_peaks[i].max), fabs (_peaks[i].min)));
+ tips[i].top = y_extent (max (fabs (_peaks[i].max), fabs (_peaks[i].min)));
if (fabs (_peaks[i].max) >= clip_level) {
tips[i].clip_max = true;
@@ -259,19 +259,19 @@ WaveView::draw_image (PeakData* _peaks, int n_peaks) const
}
if (top > 0.0) {
- top = position (alt_log_meter (fast_coefficient_to_dB (top)));
+ top = y_extent (alt_log_meter (fast_coefficient_to_dB (top)));
} else if (top < 0.0) {
- top = position (-alt_log_meter (fast_coefficient_to_dB (-top)));
+ top = y_extent (-alt_log_meter (fast_coefficient_to_dB (-top)));
} else {
- top = position (0.0);
+ top = y_extent (0.0);
}
if (bot > 0.0) {
- bot = position (alt_log_meter (fast_coefficient_to_dB (bot)));
+ bot = y_extent (alt_log_meter (fast_coefficient_to_dB (bot)));
} else if (bot < 0.0) {
- bot = position (-alt_log_meter (fast_coefficient_to_dB (-bot)));
+ bot = y_extent (-alt_log_meter (fast_coefficient_to_dB (-bot)));
} else {
- bot = position (0.0);
+ bot = y_extent (0.0);
}
tips[i].top = top;
@@ -289,8 +289,8 @@ WaveView::draw_image (PeakData* _peaks, int n_peaks) const
tips[i].clip_min = true;
}
- tips[i].top = position (_peaks[i].min);
- tips[i].bot = position (_peaks[i].max);
+ tips[i].top = y_extent (_peaks[i].min);
+ tips[i].bot = y_extent (_peaks[i].max);
}
@@ -402,8 +402,8 @@ WaveView::draw_image (PeakData* _peaks, int n_peaks) const
set_source_rgba (context, _zero_color);
context->set_line_width (1.0);
- context->move_to (0, position (0.0) + 0.5);
- context->line_to (n_peaks, position (0.0) + 0.5);
+ context->move_to (0, y_extent (0.0) + 0.5);
+ context->line_to (n_peaks, y_extent (0.0) + 0.5);
context->stroke ();
}
}
@@ -668,7 +668,7 @@ WaveView::region_resized ()
}
Coord
-WaveView::position (double s) const
+WaveView::y_extent (double s) const
{
/* it is important that this returns an integral value, so that we
can ensure correct single pixel behaviour.
diff --git a/libs/canvas/wscript b/libs/canvas/wscript
index 913f8298fa..d0cbfc882f 100644
--- a/libs/canvas/wscript
+++ b/libs/canvas/wscript
@@ -50,6 +50,7 @@ canvas_sources = [
'polygon.cc',
'rectangle.cc',
'root_group.cc',
+ 'scroll_group.cc',
'stateful_image.cc',
'text.cc',
'types.cc',