13
0

fix up major thinko's in ArdourCanvas::Group's handling of deletion (both its own, and child items)

This commit is contained in:
Paul Davis 2014-02-12 15:15:27 -05:00
parent 50edf9b626
commit e247103a7e
2 changed files with 40 additions and 12 deletions

View File

@ -68,6 +68,7 @@ private:
Group (Group const &); Group (Group const &);
void ensure_lut () const; void ensure_lut () const;
void invalidate_lut () const; void invalidate_lut () const;
void clear_items (bool with_delete);
/* our items, from lowest to highest in the stack */ /* our items, from lowest to highest in the stack */
std::list<Item*> _items; std::list<Item*> _items;

View File

@ -58,7 +58,7 @@ Group::Group (Group* parent, Duple position)
Group::~Group () Group::~Group ()
{ {
clear (true); clear_items (true);
} }
/** @param area Area to draw in this group's coordinates. /** @param area Area to draw in this group's coordinates.
@ -199,7 +199,17 @@ Group::remove (Item* i)
return; return;
} }
begin_change (); /* we cannot call bounding_box() here because that will iterate over
_items, one of which (the argument, i) may be in the middle of
deletion, making it impossible to call compute_bounding_box()
on it.
*/
if (_bounding_box) {
_pre_change_bounding_box = _bounding_box;
} else {
_pre_change_bounding_box = Rect();
}
i->unparent (); i->unparent ();
_items.remove (i); _items.remove (i);
@ -214,16 +224,7 @@ Group::clear (bool with_delete)
{ {
begin_change (); begin_change ();
for (list<Item*>::iterator i = _items.begin(); i != _items.end(); ++i) { clear_items (with_delete);
(*i)->unparent ();
if (with_delete) {
delete *i;
}
}
_items.clear ();
invalidate_lut (); invalidate_lut ();
_bounding_box_dirty = true; _bounding_box_dirty = true;
@ -231,6 +232,32 @@ Group::clear (bool with_delete)
end_change (); end_change ();
} }
void
Group::clear_items (bool with_delete)
{
for (list<Item*>::iterator i = _items.begin(); i != _items.end(); ) {
list<Item*>::iterator tmp = i;
Item *item = *i;
++tmp;
/* remove from list before doing anything else, because we
* don't want to find the item in _items during any activity
* driven by unparent-ing or deletion.
*/
_items.erase (i);
item->unparent ();
if (with_delete) {
delete item;
}
i = tmp;
}
}
void void
Group::raise_child_to_top (Item* i) Group::raise_child_to_top (Item* i)
{ {