Event handling offsets still require work.
}
/** Render an area of the canvas.
- * @param area Area in canvas coordinates.
+ * @param area Area in window coordinates.
* @param context Cairo context to render to.
*/
void
Duple
Canvas::window_to_canvas (Duple const & d) const
{
- return d.translate (Duple (_scroll_offset.x, _scroll_offset.y));
+ return d.translate (_scroll_offset);
}
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 (-_scroll_offset);
/* Note that this intentionally almost always returns integer coordinates */
void
Canvas::queue_draw_item_area (Item* item, Rect area)
{
- ArdourCanvas::Rect canvas_area = item->item_to_canvas (area);
- // cerr << "CANVAS " << this << " for " << item << ' ' << item->whatami() << ' ' << item->name << " invalidate " << area << " TRANSLATE AS " << canvas_area << " window = " << canvas_to_window (canvas_area) << std::endl;
- request_redraw (canvas_area);
+ request_redraw (item->item_to_window (area));
}
/** Construct a GtkCanvas */
}
/** Called to request a redraw of our canvas.
- * @param area Area to redraw, in canvas coordinates.
+ * @param area Area to redraw, in window coordinates.
*/
void
GtkCanvas::request_redraw (Rect const & request)
{
- boost::optional<Rect> req = request.intersection (visible_area());
-
- if (req) {
- Rect r = req.get();
- Rect area = canvas_to_window (r);
- queue_draw_area (area.x0, area.y0, area.width(), area.height());
- }
+ queue_draw_area (request.x0, request.y0, request.width(), request.height());
}
/** Called to request that we try to get a particular size for ourselves.
Canvas ();
virtual ~Canvas () {}
- /** called to request a redraw of an area of the canvas */
+ /** called to request a redraw of an area of the canvas in WINDOW coordinates */
virtual void request_redraw (Rect const &) = 0;
/** called to ask the canvas to request a particular size from its host */
virtual void request_size (Duple) = 0;
void item_moved (Item *, boost::optional<Rect>);
virtual Cairo::RefPtr<Cairo::Context> context () = 0;
-
Rect canvas_to_window (Rect const&, bool rounded = true) const;
Rect window_to_canvas (Rect const&) const;
Duple canvas_to_window (Duple const&, bool rounded = true) const;
}
void scroll_to (Coord x, Coord y);
+ Duple scroll_offset() const { return _scroll_offset; }
void add_scroller (ScrollGroup& i);
virtual Rect visible_area () const = 0;
class Canvas;
class Group;
class Rect;
+class ScrollGroup;
/** The parent class for anything that goes on the canvas.
*
return _position;
}
- virtual Duple canvas_position () const {
- return _position;
- }
-
boost::optional<Rect> bounding_box () const;
Coord height() const;
Coord width() const;
Canvas* _canvas;
/** parent group; may be 0 if we are the root group or if we have been unparent()ed */
Group* _parent;
+ /** scroll parent group; may be 0 if we are the root group or if we have been unparent()ed */
+ ScrollGroup* _scroll_parent;
/** position of this item in parent coordinates */
Duple _position;
/** true if this item is visible (ie to be drawn), otherwise false */
Duple scroll_offset() const;
Duple position_offset() const;
+
+ void find_scroll_parent ();
};
extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);
explicit ScrollGroup (Group *, Duple, ScrollSensitivity);
void scroll_to (Duple const& d);
-
- /** return the normal "base" position of this item
- rather its position as affected by any scroll
- offset.
- */
- Duple canvas_position() const {
- return _position.translate (_scroll_offset);
- }
-
Duple scroll_offset() const { return _scroll_offset; }
+
private:
ScrollSensitivity _scroll_sensitivity;
Duple _scroll_offset;
clear_items (true);
}
-/** @param area Area to draw in this group's coordinates.
+/** @param area Area to draw in window coordinates.
* @param context Context, set up with its origin at this group's position.
*/
void
_parent->add (this);
}
+ find_scroll_parent ();
+
DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this));
}
Duple
Item::scroll_offset () const
{
- Item const * i = this;
- Duple offset;
-
- while (i) {
- ScrollGroup const * sg = dynamic_cast<ScrollGroup const *> (i);
- if (sg) {
- offset = offset.translate (sg->scroll_offset());
- }
- i = i->parent();
- }
-
- return offset;
+ if (_scroll_parent) {
+ return _scroll_parent->scroll_offset();
+ }
+ return _canvas->scroll_offset();
}
Duple
Duple offset;
while (i) {
- offset = offset.translate (i->canvas_position());
+ offset = offset.translate (i->position());
i = i->parent();
}
Duple
Item::item_to_window (ArdourCanvas::Duple const & d, bool rounded) const
{
- return item_to_canvas (d).translate (-scroll_offset());
+ Duple ret = item_to_canvas (d).translate (-scroll_offset());
+
+ ret.x = round (ret.x);
+ ret.y = round (ret.y);
+
+ return ret;
}
Duple
ArdourCanvas::Rect
Item::item_to_window (ArdourCanvas::Rect const & r) const
{
- return item_to_canvas (r).translate (-scroll_offset());
+ Rect ret = item_to_canvas (r).translate (-scroll_offset());
+
+ ret.x0 = round (ret.x0);
+ ret.x1 = round (ret.x1);
+ ret.y0 = round (ret.y0);
+ ret.y1 = round (ret.y1);
+
+ return ret;
}
ArdourCanvas::Rect
Item::unparent ()
{
_parent = 0;
+ _scroll_parent = 0;
}
void
_parent = new_parent;
_canvas = _parent->canvas ();
+
+ find_scroll_parent ();
+
_parent->add (this);
}
+void
+Item::find_scroll_parent ()
+{
+ Item const * i = this;
+ ScrollGroup const * last_scroll_group = 0;
+
+ while (i) {
+ ScrollGroup const * sg = dynamic_cast<ScrollGroup const *> (i);
+ if (sg) {
+ last_scroll_group = sg;
+ }
+ i = i->parent();
+ }
+
+ _scroll_parent = const_cast<ScrollGroup*> (last_scroll_group);
+}
+
bool
Item::common_ancestor_within (uint32_t limit, const Item& other) const
{
Item::redraw () const
{
if (_visible && _bounding_box && _canvas) {
- _canvas->request_redraw (item_to_canvas (_bounding_box.get()));
+ _canvas->request_redraw (item_to_window (_bounding_box.get()));
}
}
*/
#include <iostream>
+
+#include "pbd/compose.h"
+
+#include "canvas/debug.h"
#include "canvas/scroll_group.h"
using namespace std;
void
ScrollGroup::scroll_to (Duple const& d)
{
- /* get the nominal position of the group without scroll being in effect
- */
-
- Duple base_pos (_position.translate (_scroll_offset));
-
- /* compute a new position given our sensitivity to h- and v-scrolling
- */
-
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;
}
-
- /* move there */
-
- set_position (base_pos);
}
-