X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fitem.cc;h=711743d9f1f759240f9a15f03404f4abed1f21b6;hb=5672419fffadcb41c5f402f4031fdf26a064ecc5;hp=5aef4cc779f0a856cca696fc01b2588d070101b5;hpb=d0dafc171c75146e16081c263e92190570b88a0f;p=ardour.git diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc index 5aef4cc779..711743d9f1 100644 --- a/libs/canvas/item.cc +++ b/libs/canvas/item.cc @@ -18,7 +18,7 @@ */ #include "pbd/compose.h" -#include "pbd/stacktrace.h" +#include "pbd/demangle.h" #include "pbd/convert.h" #include "ardour/utils.h" @@ -45,10 +45,8 @@ Item::Item (Canvas* canvas) , _lut (0) , _ignore_events (false) { - _tooltip = "This is a tooltip"; - DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); -} +} Item::Item (Item* parent) : Fill (*this) @@ -61,8 +59,6 @@ Item::Item (Item* parent) , _lut (0) , _ignore_events (false) { - _tooltip = "This is a tooltip"; - DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); if (parent) { @@ -70,7 +66,7 @@ Item::Item (Item* parent) } find_scroll_parent (); -} +} Item::Item (Item* parent, Duple const& p) : Fill (*this) @@ -84,8 +80,6 @@ Item::Item (Item* parent, Duple const& p) , _lut (0) , _ignore_events (false) { - _tooltip = "This is a tooltip"; - DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); if (parent) { @@ -94,7 +88,7 @@ Item::Item (Item* parent, Duple const& p) find_scroll_parent (); -} +} Item::~Item () { @@ -110,6 +104,21 @@ Item::~Item () delete _lut; } +bool +Item::visible() const +{ + Item const * i = this; + + while (i) { + if (!i->self_visible()) { + return false; + } + i = i->parent(); + } + + return true; +} + Duple Item::canvas_origin () const { @@ -117,9 +126,9 @@ Item::canvas_origin () const } Duple -Item::window_origin () const +Item::window_origin () const { - /* This is slightly subtle. Our _position is in the coordinate space of + /* This is slightly subtle. Our _position is in the coordinate space of our parent. So to find out where that is in window coordinates, we have to ask our parent. */ @@ -141,7 +150,7 @@ Item::scroll_offset () const { if (_scroll_parent) { return _scroll_parent->scroll_offset(); - } + } return Duple (0,0); } @@ -187,7 +196,7 @@ void Item::item_to_canvas (Coord& x, Coord& y) const { Duple d = item_to_canvas (Duple (x, y)); - + x = d.x; y = d.y; } @@ -222,14 +231,16 @@ Item::window_to_item (ArdourCanvas::Duple const & d) const } ArdourCanvas::Rect -Item::item_to_window (ArdourCanvas::Rect const & r) const +Item::item_to_window (ArdourCanvas::Rect const & r, bool rounded) const { 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); + if (rounded) { + ret.x0 = round (ret.x0); + ret.x1 = round (ret.x1); + ret.y0 = round (ret.y0); + ret.y1 = round (ret.y1); + } return ret; } @@ -257,13 +268,20 @@ Item::set_position (Duple p) */ pre_change_parent_bounding_box = item_to_parent (bbox.get()); } - + _position = p; - _canvas->item_moved (this, pre_change_parent_bounding_box); + /* only update canvas and parent if visible. Otherwise, this + will be done when ::show() is called. + */ - if (_parent) { - _parent->child_changed (); + if (visible()) { + _canvas->item_moved (this, pre_change_parent_bounding_box); + + + if (_parent) { + _parent->child_changed (); + } } } @@ -309,15 +327,28 @@ Item::hide () if (_visible) { _visible = false; - /* recompute parent bounding box, which may alter now that this - * child is hidden. - */ + /* children are all hidden because we are hidden, no need + to propagate change because our bounding box necessarily + includes them all already. thus our being hidden results + in (a) a redraw of the entire bounding box (b) no children + will be drawn. - if (_parent) { - _parent->child_changed (); + BUT ... current item in canvas might be one of our children, + which is now hidden. So propagate away. + */ + + for (list::iterator i = _items.begin(); i != _items.end(); ++i) { + + if ((*i)->self_visible()) { + /* item was visible but is now hidden because + we (its parent) are hidden + */ + (*i)->propagate_show_hide (); + } } - _canvas->item_shown_or_hidden (this); + + propagate_show_hide (); } } @@ -325,18 +356,34 @@ void Item::show () { if (!_visible) { - _visible = true; - /* bounding box may have changed while we were hidden */ + _visible = true; - if (_parent) { - _parent->child_changed (); + for (list::iterator i = _items.begin(); i != _items.end(); ++i) { + if ((*i)->self_visible()) { + /* item used to be hidden by us (its parent), + but is now visible + */ + (*i)->propagate_show_hide (); + } } - _canvas->item_shown_or_hidden (this); + propagate_show_hide (); } } +void +Item::propagate_show_hide () +{ + /* bounding box may have changed while we were hidden */ + + if (_parent) { + _parent->child_changed (); + } + + _canvas->item_shown_or_hidden (this); +} + Duple Item::item_to_parent (Duple const & d) const { @@ -403,7 +450,7 @@ Item::find_scroll_parent () } i = i->parent(); } - + _scroll_parent = const_cast (last_scroll_group); } @@ -414,7 +461,7 @@ Item::common_ancestor_within (uint32_t limit, const Item& other) const uint32_t d2 = other.depth(); const Item* i1 = this; const Item* i2 = &other; - + /* move towards root until we are at the same level for both items */ @@ -455,7 +502,7 @@ Item::common_ancestor_within (uint32_t limit, const Item& other) const return false; } } - + return true; } @@ -497,7 +544,7 @@ Item::closest_ancestor_with (const Item& other) const i2 = i2->parent (); } } - + return i1; } @@ -536,7 +583,7 @@ Item::bounding_box () const } Coord -Item::height () const +Item::height () const { boost::optional bb = bounding_box(); @@ -547,9 +594,9 @@ Item::height () const } Coord -Item::width () const +Item::width () const { - boost::optional bb = bounding_box().get(); + boost::optional bb = bounding_box(); if (bb) { return bb->width (); @@ -561,10 +608,10 @@ Item::width () const void Item::redraw () const { - if (_visible && _bounding_box && _canvas) { + if (visible() && _bounding_box && _canvas) { _canvas->request_redraw (item_to_window (_bounding_box.get())); } -} +} void Item::begin_change () @@ -575,9 +622,9 @@ Item::begin_change () void Item::end_change () { - if (_visible) { + if (visible()) { _canvas->item_changed (this, _pre_change_bounding_box); - + if (_parent) { _parent->child_changed (); } @@ -592,7 +639,7 @@ Item::begin_visual_change () void Item::end_visual_change () { - if (_visible) { + if (visible()) { _canvas->item_visual_property_changed (this); } } @@ -630,7 +677,7 @@ Item::get_data (string const & key) const if (i == _data.end ()) { return 0; } - + return i->second; } @@ -641,7 +688,7 @@ Item::set_ignore_events (bool ignore) } std::string -Item::whatami () const +Item::whatami () const { std::string type = demangle (typeid (*this).name()); return type.substr (type.find_last_of (':') + 1); @@ -691,14 +738,14 @@ Item::render_children (Rect const & area, Cairo::RefPtr context) #ifdef CANVAS_DEBUG if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { - cerr << string_compose ("%1%7 %2 @ %7 render %5 @ %6 %3 items out of %4\n", + cerr << string_compose ("%1%7 %2 @ %7 render %5 @ %6 %3 items out of %4\n", _canvas->render_indent(), (name.empty() ? string ("[unnamed]") : name), items.size(), _items.size(), area, _position, this, whatami()); } #endif ++render_depth; - + for (std::vector::const_iterator i = items.begin(); i != items.end(); ++i) { if (!(*i)->visible ()) { @@ -709,7 +756,7 @@ Item::render_children (Rect const & area, Cairo::RefPtr context) #endif continue; } - + boost::optional item_bbox = (*i)->bounding_box (); if (!item_bbox) { @@ -720,10 +767,10 @@ Item::render_children (Rect const & area, Cairo::RefPtr context) #endif continue; } - - Rect item = (*i)->item_to_window (item_bbox.get()); + + Rect item = (*i)->item_to_window (item_bbox.get(), false); boost::optional d = item.intersection (area); - + if (d) { Rect draw = d.get(); if (draw.width() && draw.height()) { @@ -731,7 +778,7 @@ Item::render_children (Rect const & area, Cairo::RefPtr context) if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { if (dynamic_cast(*i) == 0) { cerr << _canvas->render_indent() << "render " - << ' ' + << ' ' << (*i) << ' ' << (*i)->whatami() @@ -739,11 +786,11 @@ Item::render_children (Rect const & area, Cairo::RefPtr context) << (*i)->name << " item " << item_bbox.get() - << " window = " + << " window = " << item << " intersect = " << draw - << " @ " + << " @ " << _position << endl; } @@ -783,6 +830,10 @@ Item::add_child_bounding_boxes() const for (list::const_iterator i = _items.begin(); i != _items.end(); ++i) { + if (!(*i)->visible()) { + continue; + } + boost::optional item_bbox = (*i)->bounding_box (); if (!item_bbox) { @@ -816,6 +867,17 @@ Item::add (Item* i) _bounding_box_dirty = true; } +void +Item::add_front (Item* i) +{ + /* XXX should really notify canvas about this */ + + _items.push_front (i); + i->reparent (this); + invalidate_lut (); + _bounding_box_dirty = true; +} + void Item::remove (Item* i) { @@ -840,7 +902,7 @@ Item::remove (Item* i) _items.remove (i); invalidate_lut (); _bounding_box_dirty = true; - + end_change (); } @@ -874,7 +936,7 @@ Item::clear_items (bool with_delete) _items.erase (i); item->unparent (); - + if (with_delete) { delete item; } @@ -894,7 +956,9 @@ Item::raise_child_to_top (Item* i) _items.remove (i); _items.push_back (i); + invalidate_lut (); + redraw (); } void @@ -913,6 +977,7 @@ Item::raise_child (Item* i, int levels) _items.insert (j, i); invalidate_lut (); + redraw (); } void @@ -926,6 +991,7 @@ Item::lower_child_to_bottom (Item* i) _items.remove (i); _items.push_front (i); invalidate_lut (); + redraw (); } void @@ -1012,9 +1078,9 @@ Item::dump (ostream& o) const { boost::optional bb = bounding_box(); - o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible; + o << _canvas->indent() << whatami() << ' ' << this << " self-Visible ? " << self_visible() << " visible ? " << visible(); o << " @ " << position(); - + #ifdef CANVAS_DEBUG if (!name.empty()) { o << ' ' << name; @@ -1036,26 +1102,27 @@ Item::dump (ostream& o) const o << _canvas->indent(); o << " @ " << position(); o << " Items: " << _items.size(); - o << " Visible ? " << _visible; - + o << " Self-Visible ? " << self_visible(); + o << " Visible ? " << visible(); + boost::optional 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::const_iterator i = _items.begin(); i != _items.end(); ++i) { o << **i; } - + ArdourCanvas::dump_depth--; } }