+
+void
+Item::raise_child_to_top (Item* i)
+{
+ if (!_items.empty()) {
+ if (_items.back() == i) {
+ return;
+ }
+ }
+
+ _items.remove (i);
+ _items.push_back (i);
+
+ invalidate_lut ();
+ redraw ();
+}
+
+void
+Item::raise_child (Item* i, int levels)
+{
+ list<Item*>::iterator j = find (_items.begin(), _items.end(), i);
+ assert (j != _items.end ());
+
+ ++j;
+ _items.remove (i);
+
+ while (levels > 0 && j != _items.end ()) {
+ ++j;
+ --levels;
+ }
+
+ _items.insert (j, i);
+ invalidate_lut ();
+ redraw ();
+}
+
+void
+Item::lower_child_to_bottom (Item* i)
+{
+ if (!_items.empty()) {
+ if (_items.front() == i) {
+ return;
+ }
+ }
+ _items.remove (i);
+ _items.push_front (i);
+ invalidate_lut ();
+ redraw ();
+}
+
+void
+Item::ensure_lut () const
+{
+ if (!_lut) {
+ _lut = new DumbLookupTable (*this);
+ }
+}
+
+void
+Item::invalidate_lut () const
+{
+ delete _lut;
+ _lut = 0;
+}
+
+void
+Item::child_changed ()
+{
+ invalidate_lut ();
+ _bounding_box_dirty = true;
+
+ if (_parent) {
+ _parent->child_changed ();
+ }
+}
+
+void
+Item::add_items_at_point (Duple const point, vector<Item const *>& items) const
+{
+ boost::optional<Rect> const bbox = bounding_box ();
+
+ /* Point is in window coordinate system */
+
+ if (!bbox || !item_to_window (bbox.get()).contains (point)) {
+ return;
+ }
+
+ /* recurse and add any items within our group that contain point.
+ Our children are only considered visible if we are, and similarly
+ only if we do not ignore events.
+ */
+
+ vector<Item*> our_items;
+
+ if (!_items.empty() && visible() && !_ignore_events) {
+ ensure_lut ();
+ our_items = _lut->items_at_point (point);
+ }
+
+ if (!our_items.empty() || covers (point)) {
+ /* this adds this item itself to the list of items at point */
+ items.push_back (this);
+ }
+
+ for (vector<Item*>::iterator i = our_items.begin(); i != our_items.end(); ++i) {
+ (*i)->add_items_at_point (point, items);
+ }
+}
+
+void
+Item::set_tooltip (const std::string& s)
+{
+ _tooltip = s;
+}
+
+void
+Item::start_tooltip_timeout ()
+{
+ if (!_tooltip.empty()) {
+ _canvas->start_tooltip_timeout (this);
+ }
+}
+
+void
+Item::stop_tooltip_timeout ()
+{
+ _canvas->stop_tooltip_timeout ();
+}
+
+void
+Item::dump (ostream& o) const
+{
+ boost::optional<ArdourCanvas::Rect> bb = bounding_box();
+
+ o << _canvas->indent() << whatami() << ' ' << this << " self-Visible ? " << self_visible() << " visible ? " << visible();
+ o << " @ " << position();
+
+#ifdef CANVAS_DEBUG
+ if (!name.empty()) {
+ o << ' ' << name;
+ }
+#endif
+
+ if (bb) {
+ o << endl << _canvas->indent() << "\tbbox: " << bb.get();
+ o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb.get());
+ } else {
+ o << " bbox unset";
+ }
+
+ o << endl;
+
+ if (!_items.empty()) {
+
+#ifdef CANVAS_DEBUG
+ o << _canvas->indent();
+ o << " @ " << position();
+ o << " Items: " << _items.size();
+ o << " Self-Visible ? " << self_visible();
+ o << " Visible ? " << visible();
+
+ boost::optional<Rect> bb = bounding_box();
+
+ if (bb) {
+ o << endl << _canvas->indent() << " bbox: " << bb.get();
+ o << endl << _canvas->indent() << " CANVAS bbox: " << item_to_canvas (bb.get());
+ } else {
+ o << " bbox unset";
+ }
+
+ o << endl;
+#endif
+
+ ArdourCanvas::dump_depth++;
+
+ for (list<Item*>::const_iterator i = _items.begin(); i != _items.end(); ++i) {
+ o << **i;
+ }
+
+ ArdourCanvas::dump_depth--;
+ }
+}
+
+ostream&
+ArdourCanvas::operator<< (ostream& o, const Item& i)
+{
+ i.dump (o);
+ return o;
+}
+