summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/editor.cc9
-rw-r--r--gtk2_ardour/editor.h1
-rw-r--r--gtk2_ardour/editor_drag.cc3
-rw-r--r--gtk2_ardour/editor_mouse.cc32
-rw-r--r--gtk2_ardour/editor_summary.cc1
-rw-r--r--libs/canvas/canvas.cc189
-rw-r--r--libs/canvas/canvas/canvas.h58
-rw-r--r--libs/canvas/group.cc2
-rw-r--r--libs/canvas/item.cc1
-rw-r--r--libs/canvas/types.cc2
10 files changed, 175 insertions, 123 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 7f49c56d7b..6bae2674df 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -517,12 +517,6 @@ Editor::Editor ()
time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
- /* these enable us to have a dedicated window (for cursor setting, etc.)
- for the canvas areas.
- */
-
- track_canvas_event_box.add (*_track_canvas_viewport);
-
time_canvas_event_box.add (time_canvas_vbox);
time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
@@ -543,7 +537,7 @@ Editor::Editor ()
/* time bars canvas */
edit_packer.attach (*_time_bars_canvas_viewport, 2, 3, 1, 2, FILL, FILL, 0, 0);
/* track canvas */
- edit_packer.attach (track_canvas_event_box, 2, 3, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
+ edit_packer.attach (*_track_canvas_viewport, 2, 3, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
bottom_hbox.set_border_width (2);
bottom_hbox.set_spacing (3);
@@ -788,6 +782,7 @@ Editor::~Editor()
delete button_bindings;
delete _routes;
delete _route_groups;
+ delete _time_bars_canvas_viewport;
delete _track_canvas_viewport;
delete _drags;
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 43d3fccedf..92f60acefa 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -732,7 +732,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool track_canvas_motion (GdkEvent*);
Gtk::EventBox time_canvas_event_box;
- Gtk::EventBox track_canvas_event_box;
Gtk::EventBox time_bars_event_box;
Gtk::EventBox ruler_label_event_box;
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 701181d009..8822548ca0 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -496,10 +496,9 @@ RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView
_brushing (b),
_total_x_delta (0)
{
-
+ DEBUG_TRACE (DEBUG::Drags, "New RegionMotionDrag\n");
}
-
void
RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index de22451422..220178d18a 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -104,7 +104,7 @@ Editor::mouse_frame (framepos_t& where, bool& in_track_canvas) const
int x, y;
double wx, wy;
Gdk::ModifierType mask;
- Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->_track_canvas_viewport->get_bin_window();
+ Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->_track_canvas_viewport->get_window();
Glib::RefPtr<const Gdk::Window> pointer_window;
if (!canvas_window) {
@@ -134,6 +134,8 @@ Editor::mouse_frame (framepos_t& where, bool& in_track_canvas) const
framepos_t
Editor::event_frame (GdkEvent const * event, double* pcx, double* pcy) const
{
+ using ArdourCanvas::Duple;
+ Duple d;
double cx, cy;
if (pcx == 0) {
@@ -146,32 +148,36 @@ Editor::event_frame (GdkEvent const * event, double* pcx, double* pcy) const
*pcx = 0;
*pcy = 0;
- /* The event coordinates will be canvas coordinates */
+ /* The event coordinates will be window coordinates and we need canvas
+ * coordinates (units are pixels as with the window, but scrolling is taken into account)
+ */
switch (event->type) {
case GDK_BUTTON_RELEASE:
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
- *pcx = event->button.x;
- *pcy = event->button.y;
- _trackview_group->canvas_to_item (*pcx, *pcy);
+ d = _track_canvas->window_to_canvas (Duple (event->button.x, event->button.y));
+ *pcx = d.x;
+ *pcy = d.y;
break;
case GDK_MOTION_NOTIFY:
- *pcx = event->motion.x;
- *pcy = event->motion.y;
- _trackview_group->canvas_to_item (*pcx, *pcy);
+ d = _track_canvas->window_to_canvas (Duple (event->motion.x, event->motion.y));
+ *pcx = d.x;
+ *pcy = d.y;
break;
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
- *pcx = event->crossing.x;
- *pcy = event->crossing.y;
- /* XXX: CANVAS */
-// track_canvas->w2c(event->crossing.x, event->crossing.y, *pcx, *pcy);
+ d = _track_canvas->window_to_canvas (Duple (event->crossing.x, event->crossing.y));
+ *pcx = d.x;
+ *pcy = d.y;
break;
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
- // track_canvas->w2c(event->key.x, event->key.y, *pcx, *pcy);
+ // need to get pointer for this to work
+ // d = _track_canvas->window_to_canvas (Duple (event->key.x, event->key.y));
+ *pcx = 0;
+ *pcy = 0;
break;
default:
warning << string_compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg;
diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc
index c7aef99389..b1fa984027 100644
--- a/gtk2_ardour/editor_summary.cc
+++ b/gtk2_ardour/editor_summary.cc
@@ -680,7 +680,6 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev)
void
EditorSummary::set_editor (double const x, double const y)
{
- ArdourCanvas::checkpoint ("editor", "-> set editor");
if (_editor->pending_visual_change.idle_handler_id >= 0 && _editor->pending_visual_change.being_handled == true) {
/* As a side-effect, the Editor's visual change idle handler processes
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index 207011409e..b849894bf0 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -24,6 +24,7 @@
#include <cassert>
#include <gtkmm/adjustment.h>
+#include <gtkmm/label.h>
#include "pbd/xml++.h"
#include "pbd/compose.h"
@@ -39,6 +40,8 @@ using namespace ArdourCanvas;
Canvas::Canvas ()
: _root (this)
, _log_renders (true)
+ , _scroll_offset_x (0)
+ , _scroll_offset_y (0)
{
set_epoch ();
}
@@ -49,6 +52,8 @@ Canvas::Canvas ()
Canvas::Canvas (XMLTree const * tree)
: _root (this)
, _log_renders (true)
+ , _scroll_offset_x (0)
+ , _scroll_offset_y (0)
{
set_epoch ();
@@ -70,6 +75,13 @@ Canvas::Canvas (XMLTree const * tree)
}
}
+void
+Canvas::scroll_to (Coord x, Coord y)
+{
+ _scroll_offset_x = x;
+ _scroll_offset_y = y;
+}
+
/** Render an area of the canvas.
* @param area Area in canvas coordinates.
* @param context Cairo context to render to.
@@ -85,9 +97,21 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
}
#endif
- checkpoint ("render", "-> render");
+ // checkpoint ("render", "-> render");
render_count = 0;
+#ifdef CANVAS_DEBUG
+ if (getenv ("ARDOUR_HARLEQUIN_CANVAS")) {
+ /* light up the canvas to show redraws */
+ context->set_source_rgba (random()%255 / 255.0,
+ random()%255 / 255.0,
+ random()%255 / 255.0,
+ 255);
+ context->rectangle (area.x0, area.y0, area.width(), area.height());
+ context->fill ();
+ }
+#endif
+
context->save ();
/* clip to the requested area */
@@ -97,7 +121,7 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
boost::optional<Rect> root_bbox = _root.bounding_box();
if (!root_bbox) {
/* the root has no bounding box, so there's nothing to render */
- checkpoint ("render", "no root bbox");
+ // checkpoint ("render", "no root bbox");
context->restore ();
return;
}
@@ -107,7 +131,9 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
/* there's a common area between the root and the requested
area, so render it.
*/
- checkpoint ("render", "... root");
+ // checkpoint ("render", "... root");
+ context->stroke ();
+
_root.render (*draw, context);
}
@@ -117,7 +143,7 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
context->restore ();
- checkpoint ("render", "<- render");
+ // checkpoint ("render", "<- render");
}
ostream&
@@ -412,52 +438,6 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
}
}
-/** Construct an ImageCanvas.
- * @param size Size in pixels.
- */
-ImageCanvas::ImageCanvas (Duple size)
- : _surface (Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, size.x, size.y))
-{
- _context = Cairo::Context::create (_surface);
-}
-
-/** Construct an ImageCanvas from an XML tree.
- * @param tree XML Tree.
- * @param size Size in pixels.
- */
-ImageCanvas::ImageCanvas (XMLTree const * tree, Duple size)
- : Canvas (tree)
- , _surface (Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, size.x, size.y))
-{
- _context = Cairo::Context::create (_surface);
-}
-
-/** Render the canvas to our pixbuf.
- * @param area Area to render, in canvas coordinates.
- */
-void
-ImageCanvas::render_to_image (Rect const & area) const
-{
- render (area, _context);
-}
-
-/** Write our pixbuf to a PNG file.
- * @param f PNG file name.
- */
-void
-ImageCanvas::write_to_png (string const & f)
-{
- assert (_surface);
- _surface->write_to_png (f);
-}
-
-/** @return Our Cairo context */
-Cairo::RefPtr<Cairo::Context>
-ImageCanvas::context ()
-{
- return _context;
-}
-
/** Handler for GDK expose events.
* @param ev Event.
* @return true if the event was handled.
@@ -465,8 +445,30 @@ ImageCanvas::context ()
bool
GtkCanvas::on_expose_event (GdkEventExpose* ev)
{
+
Cairo::RefPtr<Cairo::Context> c = get_window()->create_cairo_context ();
- render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), c);
+
+ /* WINDOW CANVAS
+ * 0,0 _scroll_offset_x, _scroll_offset_y
+ */
+
+ /* render using canvas coordinates */
+
+ Rect canvas_area (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height);
+ canvas_area = canvas_area.translate (Duple (_scroll_offset_x, _scroll_offset_y));
+
+ /* things are going to render to the cairo surface with canvas
+ * coordinates:
+ *
+ * an item at window/cairo 0,0 will have canvas_coords _scroll_offset_x,_scroll_offset_y
+ *
+ * let them render at their natural coordinates by using cairo_translate()
+ */
+
+ c->translate (-_scroll_offset_x, -_scroll_offset_y);
+
+ render (canvas_area, c);
+
return true;
}
@@ -489,10 +491,18 @@ GtkCanvas::context ()
bool
GtkCanvas::on_button_press_event (GdkEventButton* ev)
{
+ /* translate event coordinates from window to canvas */
+
+ GdkEvent copy = *((GdkEvent*)ev);
+ Duple where = window_to_canvas (Duple (ev->x, ev->y));
+
+ copy.button.x = where.x;
+ copy.button.y = where.y;
+
/* Coordinates in the event will be canvas coordinates, correctly adjusted
for scroll if this GtkCanvas is in a GtkCanvasViewport.
*/
- return button_handler (ev);
+ return button_handler ((GdkEventButton*) &copy);
}
/** Handler for GDK button release events.
@@ -501,11 +511,19 @@ GtkCanvas::on_button_press_event (GdkEventButton* ev)
*/
bool
GtkCanvas::on_button_release_event (GdkEventButton* ev)
-{
+{
+ /* translate event coordinates from window to canvas */
+
+ GdkEvent copy = *((GdkEvent*)ev);
+ Duple where = window_to_canvas (Duple (ev->x, ev->y));
+
+ copy.button.x = where.x;
+ copy.button.y = where.y;
+
/* Coordinates in the event will be canvas coordinates, correctly adjusted
for scroll if this GtkCanvas is in a GtkCanvasViewport.
*/
- return button_handler (ev);
+ return button_handler ((GdkEventButton*) &copy);
}
/** Handler for GDK motion events.
@@ -515,18 +533,27 @@ GtkCanvas::on_button_release_event (GdkEventButton* ev)
bool
GtkCanvas::on_motion_notify_event (GdkEventMotion* ev)
{
+ /* translate event coordinates from window to canvas */
+
+ GdkEvent copy = *((GdkEvent*)ev);
+ Duple where = window_to_canvas (Duple (ev->x, ev->y));
+
+ copy.motion.x = where.x;
+ copy.motion.y = where.y;
+
/* Coordinates in the event will be canvas coordinates, correctly adjusted
for scroll if this GtkCanvas is in a GtkCanvasViewport.
*/
- return motion_notify_handler (ev);
+ return motion_notify_handler ((GdkEventMotion*) &copy);
}
/** Called to request a redraw of our canvas.
* @param area Area to redraw, in canvas coordinates.
*/
void
-GtkCanvas::request_redraw (Rect const & area)
+GtkCanvas::request_redraw (Rect const & request)
{
+ Rect area = canvas_to_window (request);
queue_draw_area (floor (area.x0), floor (area.y0), ceil (area.x1) - floor (area.x0), ceil (area.y1) - floor (area.y0));
}
@@ -574,17 +601,56 @@ GtkCanvas::ungrab ()
* @param vadj Adjustment to use for vertica scrolling.
*/
GtkCanvasViewport::GtkCanvasViewport (Gtk::Adjustment& hadj, Gtk::Adjustment& vadj)
- : Viewport (hadj, vadj)
+ : Alignment (0, 0, 1.0, 1.0)
+ , hadjustment (hadj)
+ , vadjustment (vadj)
{
add (_canvas);
+
+ hadj.signal_value_changed().connect (sigc::mem_fun (*this, &GtkCanvasViewport::scrolled));
+ vadj.signal_value_changed().connect (sigc::mem_fun (*this, &GtkCanvasViewport::scrolled));
}
+void
+GtkCanvasViewport::scrolled ()
+{
+ _canvas.scroll_to (hadjustment.get_value(), vadjustment.get_value());
+ queue_draw ();
+}
+
+Duple
+GtkCanvas::window_to_canvas (Duple const & d) const
+{
+ return d.translate (Duple (_scroll_offset_x, _scroll_offset_y));
+}
+
+Duple
+GtkCanvas::canvas_to_window (Duple const & d) const
+{
+ return d.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
+}
+
+Rect
+GtkCanvas::window_to_canvas (Rect const & r) const
+{
+ return r.translate (Duple (_scroll_offset_x, _scroll_offset_y));
+}
+
+Rect
+GtkCanvas::canvas_to_window (Rect const & r) const
+{
+ return r.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
+}
+
/** Handler for when GTK asks us what minimum size we want.
* @param req Requsition to fill in.
*/
void
GtkCanvasViewport::on_size_request (Gtk::Requisition* req)
{
+ /* force the canvas to size itself */
+ // _canvas.root()->bounding_box();
+
req->width = 16;
req->height = 16;
}
@@ -599,15 +665,16 @@ GtkCanvasViewport::on_size_request (Gtk::Requisition* req)
void
GtkCanvasViewport::window_to_canvas (int wx, int wy, Coord& cx, Coord& cy) const
{
- cx = wx + get_hadjustment()->get_value ();
- cy = wy + get_vadjustment()->get_value ();
+ Duple d = _canvas.window_to_canvas (Duple (wx, wy));
+ cx = d.x;
+ cy = d.y;
}
/** @return The visible area of the canvas, in canvas coordinates */
Rect
GtkCanvasViewport::visible_area () const
{
- Distance const xo = get_hadjustment()->get_value ();
- Distance const yo = get_vadjustment()->get_value ();
+ Distance const xo = hadjustment.get_value ();
+ Distance const yo = vadjustment.get_value ();
return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ());
}
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
index 7ddb7d584b..1dd339b0b4 100644
--- a/libs/canvas/canvas/canvas.h
+++ b/libs/canvas/canvas/canvas.h
@@ -26,7 +26,7 @@
#include <gdkmm/window.h>
#include <gtkmm/eventbox.h>
-#include <gtkmm/viewport.h>
+#include <gtkmm/alignment.h>
#include <cairomm/surface.h>
#include <cairomm/context.h>
#include "pbd/signals.h"
@@ -91,6 +91,8 @@ public:
_log_renders = log;
}
+ void scroll_to (Coord x, Coord y);
+
std::string indent() const;
std::string render_indent() const;
void dump (std::ostream&) const;
@@ -103,39 +105,9 @@ protected:
mutable std::list<Rect> _renders;
bool _log_renders;
-};
-
-/** A Canvas which renders onto an in-memory pixbuf. In Ardour's context,
- * this is most useful for testing.
- */
-class ImageCanvas : public Canvas
-{
-public:
- ImageCanvas (Duple size = Duple (1024, 1024));
- ImageCanvas (XMLTree const *, Duple size = Duple (1024, 1024));
-
- void request_redraw (Rect const &) {
- /* XXX */
- }
-
- void request_size (Duple) {
- /* XXX */
- }
-
- void grab (Item *) {}
- void ungrab () {}
-
- void render_to_image (Rect const &) const;
- void clear ();
- void write_to_png (std::string const &);
- Cairo::RefPtr<Cairo::Context> context ();
-
-private:
- /** our Cairo surface */
- Cairo::RefPtr<Cairo::Surface> _surface;
- /** our Cairo context */
- Cairo::RefPtr<Cairo::Context> _context;
+ Coord _scroll_offset_x;
+ Coord _scroll_offset_y;
};
/** A canvas which renders onto a GTK EventBox */
@@ -152,6 +124,12 @@ public:
Cairo::RefPtr<Cairo::Context> context ();
+ Rect canvas_to_window (Rect const&) const;
+ Rect window_to_canvas (Rect const&) const;
+
+ Duple canvas_to_window (Duple const&) const;
+ Duple window_to_canvas (Duple const&) const;
+
protected:
bool on_expose_event (GdkEventExpose *);
bool on_button_press_event (GdkEventButton *);
@@ -166,16 +144,20 @@ private:
void item_going_away (Item *, boost::optional<Rect>);
bool send_leave_event (Item const *, double, double) const;
+
/** the item that the mouse is currently over, or 0 */
Item const * _current_item;
/** the item that is currently grabbed, or 0 */
Item const * _grabbed_item;
};
-/** A GTK::Viewport with a GtkCanvas inside it. This provides a GtkCanvas
- * that can be scrolled.
+/** A GTK::Alignment with a GtkCanvas inside it plus some Gtk::Adjustments for
+ * scrolling.
+ *
+ * This provides a GtkCanvas that can be scrolled. It does NOT implement the
+ * Gtk::Scrollable interface.
*/
-class GtkCanvasViewport : public Gtk::Viewport
+class GtkCanvasViewport : public Gtk::Alignment
{
public:
GtkCanvasViewport (Gtk::Adjustment &, Gtk::Adjustment &);
@@ -194,6 +176,10 @@ protected:
private:
/** our GtkCanvas */
GtkCanvas _canvas;
+ Gtk::Adjustment& hadjustment;
+ Gtk::Adjustment& vadjustment;
+
+ void scrolled ();
};
}
diff --git a/libs/canvas/group.cc b/libs/canvas/group.cc
index 7ed0f72f74..d12c13169e 100644
--- a/libs/canvas/group.cc
+++ b/libs/canvas/group.cc
@@ -277,7 +277,7 @@ void
Group::dump (ostream& o) const
{
o << _canvas->indent();
- o << "Group " << this;
+ o << "Group " << this << " [" << name << ']';
o << " Items: " << _items.size();
o << " Visible ? " << _visible;
diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc
index 90b53b5bfd..9f34f8c208 100644
--- a/libs/canvas/item.cc
+++ b/libs/canvas/item.cc
@@ -73,6 +73,7 @@ Item::set_position (Duple p)
{
boost::optional<Rect> bbox = bounding_box ();
boost::optional<Rect> pre_change_parent_bounding_box;
+
if (bbox) {
pre_change_parent_bounding_box = item_to_parent (bbox.get());
}
diff --git a/libs/canvas/types.cc b/libs/canvas/types.cc
index 8d7fbf1c27..ef5d3bb293 100644
--- a/libs/canvas/types.cc
+++ b/libs/canvas/types.cc
@@ -52,7 +52,7 @@ Rect
Rect::translate (Duple t) const
{
Rect r;
-
+
r.x0 = safe_add (x0, t.x);
r.y0 = safe_add (y0, t.y);
r.x1 = safe_add (x1, t.x);