diff --git a/direct/src/gui/Frame.py b/direct/src/gui/Frame.py index a65dac2f53..668d0193fe 100644 --- a/direct/src/gui/Frame.py +++ b/direct/src/gui/Frame.py @@ -72,6 +72,7 @@ class Frame: for itemNum in range(1, len(self.items)): self.packItem(itemNum, GuiFrame.GuiFrame.UNDER, itemNum - 1) self.packItem(itemNum, GuiFrame.GuiFrame.ALIGNLEFT, itemNum - 1) + self.frame.recompute() def makeHorizontal(self): # remove any previous packing @@ -80,6 +81,7 @@ class Frame: for itemNum in range(1, len(self.items)): self.packItem(itemNum, GuiFrame.GuiFrame.RIGHT, itemNum - 1) self.packItem(itemNum, GuiFrame.GuiFrame.ALIGNABOVE, itemNum - 1) + self.frame.recompute() def makeWideAsWidest(self): # make all the buttons as wide as the widest button in diff --git a/panda/src/gui/guiButton.cxx b/panda/src/gui/guiButton.cxx index c2608bcd71..0e1a062c38 100644 --- a/panda/src/gui/guiButton.cxx +++ b/panda/src/gui/guiButton.cxx @@ -15,6 +15,17 @@ static ButtonMap buttons; TypeHandle GuiButton::_type_handle; + +static GuiButton * +find_in_buttons_map(const string &name) { + ButtonMap::const_iterator bi; + bi = buttons.find(name); + if (bi == buttons.end()) { + return (GuiButton *)NULL; + } + return (*bi).second; +} + inline void GetExtents(GuiLabel* v, GuiLabel* w, GuiLabel* x, GuiLabel* y, GuiLabel* z, float& l, float& r, float& b, float& t) { float l1, l2, r1, r2, b1, b2, t1, t2; @@ -48,21 +59,46 @@ inline void GetExtents(GuiLabel* v, GuiLabel* w, GuiLabel* x, GuiLabel* y, } static void enter_button(CPT_Event e) { - GuiButton* val = buttons[e->get_name()]; + GuiButton* val = find_in_buttons_map(e->get_name()); + if (val == (GuiButton *)NULL) { + if (gui_cat.is_debug()) { + gui_cat.debug() + << "Ignoring event " << e->get_name() << " for deleted button\n"; + } + return; + } + val->test_ref_count_integrity(); val->enter(); } static void exit_button(CPT_Event e) { - GuiButton* val = buttons[e->get_name()]; + GuiButton* val = find_in_buttons_map(e->get_name()); + if (val == (GuiButton *)NULL) { + if (gui_cat.is_debug()) { + gui_cat.debug() + << "Ignoring event " << e->get_name() << " for deleted button\n"; + } + return; + } + val->test_ref_count_integrity(); val->exit(); } static void click_button(CPT_Event e) { - GuiButton* val = buttons[e->get_name()]; + GuiButton* val = find_in_buttons_map(e->get_name()); + if (val == (GuiButton *)NULL) { + if (gui_cat.is_debug()) { + gui_cat.debug() + << "Ignoring event " << e->get_name() << " for deleted button\n"; + } + return; + } + val->test_ref_count_integrity(); val->click(); } void GuiButton::switch_state(GuiButton::States nstate) { + test_ref_count_integrity(); // cleanup old state switch (_state) { case NONE: @@ -231,6 +267,15 @@ GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* up_roll, GuiButton::~GuiButton(void) { this->unmanage(); + + // Remove the names from the buttons map, so we don't end up with + // an invalid pointer. + string name = get_name(); + buttons.erase("gui-in-button-" + name); + buttons.erase("gui-out-button-" + name); + buttons.erase("gui-button-" + name + "-mouse1"); + buttons.erase("gui-button-" + name + "-mouse2"); + buttons.erase("gui-button-" + name + "-mouse3"); } void GuiButton::manage(GuiManager* mgr, EventHandler& eh) { diff --git a/panda/src/gui/guiItem.cxx b/panda/src/gui/guiItem.cxx index 9b3ed7b13f..e4489d9703 100644 --- a/panda/src/gui/guiItem.cxx +++ b/panda/src/gui/guiItem.cxx @@ -8,6 +8,7 @@ TypeHandle GuiItem::_type_handle; void GuiItem::recompute_frame(void) { + test_ref_count_integrity(); } GuiItem::GuiItem(const string& name) : Namable(name), _added_hooks(false), @@ -24,10 +25,12 @@ GuiItem::~GuiItem(void) { } void GuiItem::manage(GuiManager* mgr, EventHandler&) { + test_ref_count_integrity(); _mgr = mgr; } void GuiItem::unmanage(void) { + test_ref_count_integrity(); _mgr = (GuiManager*)0L; } diff --git a/panda/src/gui/guiManager.cxx b/panda/src/gui/guiManager.cxx index f3f3cacc7f..29a3f11f26 100644 --- a/panda/src/gui/guiManager.cxx +++ b/panda/src/gui/guiManager.cxx @@ -118,6 +118,7 @@ GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak) { } void GuiManager::add_region(GuiRegion* region) { + region->test_ref_count_integrity(); RegionSet::const_iterator ri; ri = _regions.find(region); if (ri == _regions.end()) { @@ -129,6 +130,7 @@ void GuiManager::add_region(GuiRegion* region) { } void GuiManager::add_label(GuiLabel* label) { + label->test_ref_count_integrity(); LabelSet::const_iterator li; li = _labels.find(label); if (li == _labels.end()) { @@ -141,6 +143,7 @@ void GuiManager::add_label(GuiLabel* label) { } void GuiManager::remove_region(GuiRegion* region) { + region->test_ref_count_integrity(); RegionSet::iterator ri; ri = _regions.find(region); if (ri == _regions.end()) @@ -153,6 +156,7 @@ void GuiManager::remove_region(GuiRegion* region) { } void GuiManager::remove_label(GuiLabel* label) { + label->test_ref_count_integrity(); LabelSet::iterator li; li = _labels.find(label); if (li == _labels.end()) diff --git a/panda/src/gui/guiRegion.I b/panda/src/gui/guiRegion.I index 34e015eca3..805df2316d 100644 --- a/panda/src/gui/guiRegion.I +++ b/panda/src/gui/guiRegion.I @@ -15,15 +15,21 @@ INLINE GuiRegion::GuiRegion(const string& name, float l, float r, float b, } INLINE MouseWatcherRegion* GuiRegion::get_region(void) const { + test_ref_count_integrity(); + _region->test_ref_count_integrity(); return _region; } INLINE void GuiRegion::trap_clicks(bool t) { + test_ref_count_integrity(); + _region->test_ref_count_integrity(); _region->set_suppress_below(t); } INLINE void GuiRegion::set_region(float left, float right, float bottom, float top) { + test_ref_count_integrity(); + _region->test_ref_count_integrity(); _region->set_frame(left, right, bottom, top); _left = left; _right = right; @@ -32,5 +38,7 @@ INLINE void GuiRegion::set_region(float left, float right, float bottom, } INLINE LVector4f GuiRegion::get_frame(void) const { + test_ref_count_integrity(); + _region->test_ref_count_integrity(); return LVector4f(_left, _right, _bottom, _top); } diff --git a/panda/src/gui/guiRollover.cxx b/panda/src/gui/guiRollover.cxx index 2125b8b43d..8a9d4eb84c 100644 --- a/panda/src/gui/guiRollover.cxx +++ b/panda/src/gui/guiRollover.cxx @@ -13,6 +13,17 @@ static RolloverMap rollovers; TypeHandle GuiRollover::_type_handle; + +static GuiRollover * +find_in_rollovers_map(const string &name) { + RolloverMap::const_iterator bi; + bi = rollovers.find(name); + if (bi == rollovers.end()) { + return (GuiRollover *)NULL; + } + return (*bi).second; +} + inline void GetExtents(GuiLabel* x, GuiLabel* y, float& l, float& r, float& b, float& t) { float l1, l2, r1, r2, b1, b2, t1, t2; @@ -25,12 +36,26 @@ inline void GetExtents(GuiLabel* x, GuiLabel* y, float& l, float& r, float& b, } static void enter_rollover(CPT_Event e) { - GuiRollover* val = rollovers[e->get_name()]; + GuiRollover* val = find_in_rollovers_map(e->get_name()); + if (val == (GuiRollover *)NULL) { + if (gui_cat.is_debug()) { + gui_cat.debug() + << "Ignoring event " << e->get_name() << " for deleted rollover\n"; + } + return; + } val->enter(); } static void exit_rollover(CPT_Event e) { - GuiRollover* val = rollovers[e->get_name()]; + GuiRollover* val = find_in_rollovers_map(e->get_name()); + if (val == (GuiRollover *)NULL) { + if (gui_cat.is_debug()) { + gui_cat.debug() + << "Ignoring event " << e->get_name() << " for deleted rollover\n"; + } + return; + } val->exit(); } @@ -54,6 +79,12 @@ GuiRollover::GuiRollover(const string& name, GuiLabel* off, GuiLabel* on) GuiRollover::~GuiRollover(void) { this->unmanage(); + + // Remove the names from the rollovers map, so we don't end up with + // an invalid pointer. + string name = get_name(); + rollovers.erase("gui-in-rollover-" + name); + rollovers.erase("gui-out-rollover-" + name); } void GuiRollover::manage(GuiManager* mgr, EventHandler& eh) { diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index 184ca9542b..a8e517afe0 100644 --- a/panda/src/tform/mouseWatcher.cxx +++ b/panda/src/tform/mouseWatcher.cxx @@ -79,6 +79,12 @@ has_region(MouseWatcherRegion *region) const { //////////////////////////////////////////////////////////////////// bool MouseWatcher:: remove_region(MouseWatcherRegion *region) { + if (region == _current_region) { + _current_region = (MouseWatcherRegion *)NULL; + } + if (region == _button_down_region) { + _button_down_region = (MouseWatcherRegion *)NULL; + } return _regions.erase(region) != 0; } @@ -151,6 +157,11 @@ write(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// void MouseWatcher:: set_current_region(MouseWatcherRegion *region) { +#ifndef NDEBUG + if (region != (MouseWatcherRegion *)NULL) { + region->test_ref_count_integrity(); + } +#endif if (region != _current_region) { if (_current_region != (MouseWatcherRegion *)NULL) { throw_event_pattern(_leave_pattern, _current_region); @@ -171,6 +182,7 @@ set_current_region(MouseWatcherRegion *region) { void MouseWatcher:: throw_event_pattern(const string &pattern, const MouseWatcherRegion *region, const string &button_name) { + region->test_ref_count_integrity(); if (pattern.empty()) { return; }