Fix some capitalisation in the preferences dialog.
[ardour.git] / libs / canvas / canvas.cc
index 5e5fd6e7277ef7fc506976fb00af80bada7c6416..d5d85623612c33f8bbe1a54ca28fada03a5c49b2 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "canvas/canvas.h"
 #include "canvas/debug.h"
+#include "canvas/line.h"
 
 using namespace std;
 using namespace ArdourCanvas;
@@ -69,7 +70,7 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
 {
 #ifdef CANVAS_DEBUG
        if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
-               cerr << "RENDER: " << area << endl;
+               cerr << this << " RENDER: " << area << endl;
                //cerr << "CANVAS @ " << this << endl;
                //dump (cerr);
                //cerr << "-------------------------\n";
@@ -261,7 +262,7 @@ void
 Canvas::queue_draw_item_area (Item* item, Rect area)
 {
        ArdourCanvas::Rect canvas_area = item->item_to_canvas (area);
-       // cerr << "CANVAS " << this << " for " << item->whatami() << ' ' << item->name << " invalidate " << area << " TRANSLATE AS " << canvas_area << endl;
+       // 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);
 }
 
@@ -311,6 +312,20 @@ GtkCanvas::pick_current_item (Duple const & point, int state)
        vector<Item const *> items;
        _root.add_items_at_point (point, items);
 
+       DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("%1 covers %2 items\n", point, items.size()));
+
+#ifndef NDEBUG
+       if (DEBUG_ENABLED(PBD::DEBUG::CanvasEnterLeave)) {
+               for (vector<Item const*>::const_iterator it = items.begin(); it != items.end(); ++it) {
+#ifdef CANVAS_DEBUG
+                       std::cerr << "\tItem " << (*it)->whatami() << '/' << (*it)->name << std::endl;
+#else
+                       std::cerr << "\tItem " << (*it)->whatami() << std::endl;
+#endif
+               }
+       }
+#endif
+
        /* put all items at point that are event-sensitive and visible and NOT
           groups into within_items. Note that items is sorted from bottom to
           top, but we're going to reverse that for within_items so that its
@@ -336,6 +351,7 @@ GtkCanvas::pick_current_item (Duple const & point, int state)
        if (within_items.empty()) {
 
                /* no items at point, just send leave event below */
+               _new_current_item = 0;
 
        } else {
 
@@ -343,7 +359,7 @@ GtkCanvas::pick_current_item (Duple const & point, int state)
                        /* uppermost item at point is already _current_item */
                        return;
                }
-               
+       
                _new_current_item = const_cast<Item*> (within_items.front());
        }
 
@@ -465,7 +481,7 @@ GtkCanvas::deliver_enter_leave (Duple const & point, int state)
        if (_current_item && !_current_item->ignore_events ()) {
                leave_event.detail = leave_detail;
                _current_item->Event ((GdkEvent*)&leave_event);
-               // std::cerr << "LEAVE " << _current_item->whatami() << '/' << _current_item->name << std::endl;
+               DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("LEAVE %1/%2\n", _current_item->whatami(), _current_item->name));
        }
 
        leave_event.detail = GDK_NOTIFY_VIRTUAL;
@@ -473,13 +489,14 @@ GtkCanvas::deliver_enter_leave (Duple const & point, int state)
 
        for (vector<Item*>::iterator it = items_to_leave_virtual.begin(); it != items_to_leave_virtual.end(); ++it) {
                if (!(*it)->ignore_events()) {
+                       DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("leave %1/%2\n", (*it)->whatami(), (*it)->name));
                        (*it)->Event ((GdkEvent*)&leave_event);
-                       // std::cerr << "leave " << (*it)->whatami() << '/' << (*it)->name << std::endl;
                }
        }
 
        for (vector<Item*>::iterator it = items_to_enter_virtual.begin(); it != items_to_enter_virtual.end(); ++it) {
                if (!(*it)->ignore_events()) {
+                       DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("enter %1/%2\n", (*it)->whatami(), (*it)->name));
                        (*it)->Event ((GdkEvent*)&enter_event);
                        // std::cerr << "enter " << (*it)->whatami() << '/' << (*it)->name << std::endl;
                }
@@ -487,8 +504,8 @@ GtkCanvas::deliver_enter_leave (Duple const & point, int state)
 
        if (_new_current_item && !_new_current_item->ignore_events()) {
                enter_event.detail = enter_detail;
+               DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("ENTER %1/%2\n", _new_current_item->whatami(), _new_current_item->name));
                _new_current_item->Event ((GdkEvent*)&enter_event);
-               // std::cerr << "ENTER " << _new_current_item->whatami() << '/' << _new_current_item->name << std::endl;
        }
 
        _current_item = _new_current_item;
@@ -505,20 +522,24 @@ GtkCanvas::deliver_event (GdkEvent* event)
 {
        /* Point in in canvas coordinate space */
 
+       const Item* event_item;
+
        if (_grabbed_item) {
                /* we have a grabbed item, so everything gets sent there */
                DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("%1 %2 (%3) was grabbed, send event there\n",
                                                                       _grabbed_item, _grabbed_item->whatami(), _grabbed_item->name));
-               return _grabbed_item->Event (event);
+               event_item = _grabbed_item;
+       } else {
+               event_item = _current_item;
        }
 
-       if (!_current_item) {
+       if (!event_item) {
                return false;
        }
 
        /* run through the items from child to parent, until one claims the event */
 
-       Item* item = const_cast<Item*> (_current_item);
+       Item* item = const_cast<Item*> (event_item);
        
        while (item) {
 
@@ -535,7 +556,7 @@ GtkCanvas::deliver_event (GdkEvent* event)
                        return true;
                }
                
-               DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas event left unhandled by %1 %2\n", item->whatami(), item->name.empty() ? "[unknown]" : item->name));
+               DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas event %3 left unhandled by %1 %2\n", item->whatami(), item->name.empty() ? "[unknown]" : item->name, event_type_string (event->type)));
 
                if ((item = parent) == 0) {
                        break;
@@ -557,17 +578,10 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
                queue_draw_item_area (item, bounding_box.get ());
        }
        
-       /* no need to send a leave event to this item, since it is going away 
-        */
-
        if (_new_current_item == item) {
                _new_current_item = 0;
        }
 
-       if (_current_item == item) {
-               _current_item = 0;
-       }
-
        if (_grabbed_item == item) {
                _grabbed_item = 0;
        }
@@ -576,7 +590,12 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
                _focused_item = 0;
        }
 
-       pick_current_item (0); // no mouse state
+       if (_current_item == item) {
+               /* no need to send a leave event to this item, since it is going away 
+                */
+               _current_item = 0;
+               pick_current_item (0); // no mouse state
+       }
        
 }
 
@@ -587,10 +606,8 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
 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);
-
+       Cairo::RefPtr<Cairo::Context> cairo_context = 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), cairo_context);
        return true;
 }
 
@@ -677,15 +694,6 @@ GtkCanvas::on_motion_notify_event (GdkEventMotion* ev)
 
        // DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas motion @ %1, %2\n", ev->x, ev->y));
 
-       if (_grabbed_item) {
-               /* if we have a grabbed item, it gets just the motion event,
-                  since no enter/leave events can have happened.
-               */
-               DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("%1 %2 (%3) was grabbed, send MOTION event there\n",
-                                                                      _grabbed_item, _grabbed_item->whatami(), _grabbed_item->name));
-               return _grabbed_item->Event (reinterpret_cast<GdkEvent*> (&copy));
-       }
-
        pick_current_item (where, ev->state);
 
        /* Now deliver the motion event.  It may seem a little inefficient
@@ -720,8 +728,13 @@ GtkCanvas::on_leave_notify_event (GdkEventCrossing* ev)
 void
 GtkCanvas::request_redraw (Rect const & request)
 {
-       Rect area = canvas_to_window (request);
-       queue_draw_area (area.x0, area.y0, area.width(), area.height());
+       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());
+       }
 }
 
 /** Called to request that we try to get a particular size for ourselves.