Reimplementation of large parts of the WaveView class
[ardour.git] / libs / canvas / item.cc
index 706a62b717e0fd8ea697a6f6f4d4dd0ca5d77f16..98fe6362dba6298711206ee0bbb7a930f83ea12f 100644 (file)
@@ -259,14 +259,14 @@ Item::set_position (Duple p)
                return;
        }
 
-       boost::optional<ArdourCanvas::Rect> bbox = bounding_box ();
-       boost::optional<ArdourCanvas::Rect> pre_change_parent_bounding_box;
+       ArdourCanvas::Rect bbox = bounding_box ();
+       ArdourCanvas::Rect pre_change_parent_bounding_box;
 
        if (bbox) {
                /* see the comment in Canvas::item_moved() to understand
                 * why we use the parent's bounding box here.
                 */
-               pre_change_parent_bounding_box = item_to_parent (bbox.get());
+               pre_change_parent_bounding_box = item_to_parent (bbox);
        }
 
        _position = p;
@@ -571,9 +571,15 @@ Item::grab_focus ()
        /* XXX */
 }
 
+void
+Item::size_allocate (Rect const & r)
+{
+       _allocation = r;
+}
+
 /** @return Bounding box in this item's coordinates */
-boost::optional<ArdourCanvas::Rect>
-Item::bounding_box () const
+ArdourCanvas::Rect
+Item::bounding_box (bool for_own_purposes) const
 {
        if (_bounding_box_dirty) {
                compute_bounding_box ();
@@ -581,16 +587,22 @@ Item::bounding_box () const
                add_child_bounding_boxes ();
        }
 
+       if (!for_own_purposes) {
+               if (_allocation) {
+                       return _allocation;
+               }
+       }
+
        return _bounding_box;
 }
 
 Coord
 Item::height () const
 {
-       boost::optional<ArdourCanvas::Rect> bb  = bounding_box();
+       ArdourCanvas::Rect bb  = bounding_box();
 
        if (bb) {
-               return bb->height ();
+               return bb.height ();
        }
        return 0;
 }
@@ -598,10 +610,10 @@ Item::height () const
 Coord
 Item::width () const
 {
-       boost::optional<ArdourCanvas::Rect> bb = bounding_box();
+       ArdourCanvas::Rect bb = bounding_box();
 
        if (bb) {
-               return bb->width ();
+               return bb.width ();
        }
 
        return 0;
@@ -611,7 +623,7 @@ void
 Item::redraw () const
 {
        if (visible() && _bounding_box && _canvas) {
-               _canvas->request_redraw (item_to_window (_bounding_box.get()));
+               _canvas->request_redraw (item_to_window (_bounding_box));
        }
 }
 
@@ -717,13 +729,13 @@ Item::covers (Duple const & point) const
                compute_bounding_box ();
        }
 
-       boost::optional<Rect> r = bounding_box();
+       Rect r = bounding_box();
 
        if (!r) {
                return false;
        }
 
-       return r.get().contains (p);
+       return r.contains (p);
 }
 
 /* nesting/grouping API */
@@ -759,7 +771,7 @@ Item::render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context)
                        continue;
                }
 
-               boost::optional<Rect> item_bbox = (*i)->bounding_box ();
+               Rect item_bbox = (*i)->bounding_box ();
 
                if (!item_bbox) {
 #ifdef CANVAS_DEBUG
@@ -770,11 +782,11 @@ Item::render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context)
                        continue;
                }
 
-               Rect item = (*i)->item_to_window (item_bbox.get(), false);
-               boost::optional<Rect> d = item.intersection (area);
+               Rect item = (*i)->item_to_window (item_bbox, false);
+               Rect d = item.intersection (area);
 
                if (d) {
-                       Rect draw = d.get();
+                       Rect draw = d;
                        if (draw.width() && draw.height()) {
 #ifdef CANVAS_DEBUG
                                if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
@@ -787,7 +799,7 @@ Item::render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context)
                                                     << ' '
                                                     << (*i)->name
                                                     << " item "
-                                                    << item_bbox.get()
+                                                    << item_bbox
                                                     << " window = "
                                                     << item
                                                     << " intersect = "
@@ -818,15 +830,52 @@ Item::render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context)
        --render_depth;
 }
 
+void
+Item::prepare_for_render_children (Rect const & area) const
+{
+       if (_items.empty()) {
+               return;
+       }
+
+       ensure_lut ();
+       std::vector<Item*> items = _lut->get (area);
+
+       for (std::vector<Item*>::const_iterator i = items.begin(); i != items.end(); ++i) {
+
+               if (!(*i)->visible ()) {
+                       continue;
+               }
+
+               Rect item_bbox = (*i)->bounding_box ();
+
+               if (!item_bbox) {
+                       continue;
+               }
+
+               Rect item = (*i)->item_to_window (item_bbox, false);
+               Rect d = item.intersection (area);
+
+               if (d) {
+                       Rect draw = d;
+                       if (draw.width() && draw.height()) {
+                               (*i)->prepare_for_render (area);
+                       }
+
+               } else {
+                       // Item does not intersect with visible canvas area
+               }
+       }
+}
+
 void
 Item::add_child_bounding_boxes (bool include_hidden) const
 {
-       boost::optional<Rect> self;
+       Rect self;
        Rect bbox;
        bool have_one = false;
 
        if (_bounding_box) {
-               bbox = _bounding_box.get();
+               bbox = _bounding_box;
                have_one = true;
        }
 
@@ -836,13 +885,13 @@ Item::add_child_bounding_boxes (bool include_hidden) const
                        continue;
                }
 
-               boost::optional<Rect> item_bbox = (*i)->bounding_box ();
+               Rect item_bbox = (*i)->bounding_box ();
 
                if (!item_bbox) {
                        continue;
                }
 
-               Rect group_bbox = (*i)->item_to_parent (item_bbox.get ());
+               Rect group_bbox = (*i)->item_to_parent (item_bbox);
                if (have_one) {
                        bbox = bbox.extend (group_bbox);
                } else {
@@ -852,7 +901,7 @@ Item::add_child_bounding_boxes (bool include_hidden) const
        }
 
        if (!have_one) {
-               _bounding_box = boost::optional<Rect> ();
+               _bounding_box = Rect ();
        } else {
                _bounding_box = bbox;
        }
@@ -1025,11 +1074,11 @@ Item::child_changed ()
 void
 Item::add_items_at_point (Duple const point, vector<Item const *>& items) const
 {
-       boost::optional<Rect> const bbox = bounding_box ();
+       Rect const bbox = bounding_box ();
 
        /* Point is in window coordinate system */
 
-       if (!bbox || !item_to_window (bbox.get()).contains (point)) {
+       if (!bbox || !item_to_window (bbox).contains (point)) {
                return;
        }
 
@@ -1078,7 +1127,7 @@ Item::stop_tooltip_timeout ()
 void
 Item::dump (ostream& o) const
 {
-       boost::optional<ArdourCanvas::Rect> bb = bounding_box();
+       ArdourCanvas::Rect bb = bounding_box();
 
        o << _canvas->indent() << whatami() << ' ' << this << " self-Visible ? " << self_visible() << " visible ? " << visible();
        o << " @ " << position();
@@ -1090,8 +1139,8 @@ Item::dump (ostream& o) const
 #endif
 
        if (bb) {
-               o << endl << _canvas->indent() << "\tbbox: " << bb.get();
-               o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb.get());
+               o << endl << _canvas->indent() << "\tbbox: " << bb;
+               o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb);
        } else {
                o << " bbox unset";
        }
@@ -1107,11 +1156,11 @@ Item::dump (ostream& o) const
                o << " Self-Visible ? " << self_visible();
                o << " Visible ? " << visible();
 
-               boost::optional<Rect> bb = bounding_box();
+               Rect bb = bounding_box();
 
                if (bb) {
-                       o << endl << _canvas->indent() << "  bbox: " << bb.get();
-                       o << endl << _canvas->indent() << "  CANVAS bbox: " << item_to_canvas (bb.get());
+                       o << endl << _canvas->indent() << "  bbox: " << bb;
+                       o << endl << _canvas->indent() << "  CANVAS bbox: " << item_to_canvas (bb);
                } else {
                        o << "  bbox unset";
                }