Răsfoiți Sursa

Times, they are a changing

Cary Sandvig 25 ani în urmă
părinte
comite
3b5c21e1dd

+ 0 - 3
panda/src/gui/Sources.pp

@@ -15,7 +15,6 @@
   #define SOURCES \
     config_gui.h config_gui.cxx \
     guiManager.h guiManager.I guiManager.cxx \
-    guiRegion.h guiRegion.I guiRegion.cxx \
     guiLabel.h guiLabel.I guiLabel.cxx \
     guiItem.h guiItem.I guiItem.cxx \
     guiRollover.h guiRollover.I guiRollover.cxx \
@@ -30,7 +29,6 @@
 
   #define INSTALL_HEADERS \
     guiManager.h guiManager.I \
-    guiRegion.h guiRegion.I \
     guiLabel.h guiLabel.I \
     guiItem.h guiItem.I \
     guiRollover.h guiRollover.I \
@@ -45,7 +43,6 @@
 
   #define IGATESCAN \
     guiManager.h guiManager.I \
-    guiRegion.h guiRegion.I \
     guiLabel.h guiLabel.I \
     guiItem.h guiItem.I \
     guiRollover.h guiRollover.I \

+ 0 - 2
panda/src/gui/config_gui.cxx

@@ -5,7 +5,6 @@
 
 #include "config_gui.h"
 #include "guiLabel.h"
-#include "guiRegion.h"
 #include "guiItem.h"
 #include "guiSign.h"
 #include "guiRollover.h"
@@ -24,7 +23,6 @@ NotifyCategoryDef(gui, "");
 
 ConfigureFn(config_gui) {
   GuiLabel::init_type();
-  GuiRegion::init_type();
   GuiItem::init_type();
   GuiBehavior::init_type();
   GuiSign::init_type();

+ 0 - 4
panda/src/gui/guiBackground.cxx

@@ -57,8 +57,6 @@ GuiBackground::~GuiBackground(void) {
 }
 
 void GuiBackground::manage(GuiManager* mgr, EventHandler& eh) {
-  if (!_added_hooks)
-    _added_hooks = true;
   if (_mgr == (GuiManager*)0L) {
     mgr->add_label(_bg);
     _item->manage(mgr, eh);
@@ -69,8 +67,6 @@ void GuiBackground::manage(GuiManager* mgr, EventHandler& eh) {
 }
 
 void GuiBackground::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
-  if (!_added_hooks)
-    _added_hooks = true;
   if (_mgr == (GuiManager*)0L) {
     mgr->add_label(_bg, n);
     _item->manage(mgr, eh, n);

+ 12 - 10
panda/src/gui/guiButton.I

@@ -6,6 +6,10 @@
 INLINE GuiButton::GuiButton(void) {
 }
 
+INLINE bool GuiButton::owns_region(const MouseWatcherRegion* rgn) const {
+  return (_rgn == rgn);
+}
+
 INLINE void GuiButton::enter(void) {
   switch (_state) {
   case UP:
@@ -140,43 +144,41 @@ INLINE bool GuiButton::is_active(void) const {
 INLINE void GuiButton::set_up_event(const string& s) {
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->remove_hook(_up_event, GuiButton::behavior_up, (void*)this);
+      _eh->remove_hook(_up_event, GuiButton::behavior_up);
   _up_event = s;
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->add_hook(_up_event, GuiButton::behavior_up, (void*)this);
+      _eh->add_hook(_up_event, GuiButton::behavior_up);
 }
 
 INLINE void GuiButton::set_up_rollover_event(const string& s) {
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up,
-		       (void*)this);
+      _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up);
   _up_rollover_event = s;
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->add_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
+      _eh->add_hook(_up_rollover_event, GuiButton::behavior_up);
 }
 
 INLINE void GuiButton::set_down_event(const string& s) {
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->remove_hook(_down_event, GuiButton::behavior_up, (void*)this);
+      _eh->remove_hook(_down_event, GuiButton::behavior_up);
   _down_event = s;
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->add_hook(_down_event, GuiButton::behavior_up, (void*)this);
+      _eh->add_hook(_down_event, GuiButton::behavior_up);
 }
 
 INLINE void GuiButton::set_down_rollover_event(const string& s) {
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->remove_hook(_down_rollover_event, GuiButton::behavior_up,
-		       (void*)this);
+      _eh->remove_hook(_down_rollover_event, GuiButton::behavior_up);
   _down_rollover_event = s;
   if (_behavior_running)
     if (_mgr != (GuiManager*)0L)
-      _eh->add_hook(_down_rollover_event, GuiButton::behavior_up, (void*)this);
+      _eh->add_hook(_down_rollover_event, GuiButton::behavior_up);
 }
 
 INLINE void GuiButton::set_inactive_event(const string& s) {

+ 259 - 260
panda/src/gui/guiButton.cxx

@@ -8,22 +8,21 @@
 
 #include <throw_event.h>
 
-#include <map>
+#include <set>
 
-typedef map<string, GuiButton*> ButtonMap;
-static ButtonMap buttons;
+typedef set<GuiButton*> ButtonSet;
+static ButtonSet buttons;
+static bool added_hooks = false;
 
 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;
+find_in_buttons_set(const MouseWatcherRegion* rgn) {
+  for (ButtonSet::const_iterator bi=buttons.begin(); bi!=buttons.end(); ++bi)
+    if ((*bi)->owns_region(rgn))
+      return *bi;
+  return (GuiButton*)0L;
 }
 
 inline void GetExtents(GuiLabel* v, GuiLabel* w, GuiLabel* x, GuiLabel* y,
@@ -59,97 +58,77 @@ inline void GetExtents(GuiLabel* v, GuiLabel* w, GuiLabel* x, GuiLabel* y,
 }
 
 static void enter_button(CPT_Event e) {
-  GuiButton* val = find_in_buttons_map(e->get_name());
-  if (val == (GuiButton *)NULL) {
-#ifdef _DEBUG
-    if (gui_cat.is_debug())
-      gui_cat.debug()
-	<< "Ignoring event " << e->get_name() << " for deleted button\n";
-#endif
-    return;
-  }
+  const MouseWatcherRegion* rgn = DCAST(MouseWatcherRegion, e->get_parameter(0).get_ptr());
+  GuiButton* val = find_in_buttons_set(rgn);
+  if (val == (GuiButton *)0L)
+    return;  // this one wasn't for us
   val->test_ref_count_integrity();
   val->enter();
 }
 
 static void exit_button(CPT_Event e) {
-  GuiButton* val = find_in_buttons_map(e->get_name());
-  if (val == (GuiButton *)NULL) {
-#ifdef _DEBUG
-    if (gui_cat.is_debug())
-      gui_cat.debug()
-	<< "Ignoring event " << e->get_name() << " for deleted button\n";
-#endif
-    return;
-  }
+  const MouseWatcherRegion* rgn = DCAST(MouseWatcherRegion, e->get_parameter(0).get_ptr());
+  GuiButton* val = find_in_buttons_set(rgn);
+  if (val == (GuiButton *)0L)
+    return;  // this one wasn't for us
   val->test_ref_count_integrity();
   val->exit();
 }
 
 static void click_button_down(CPT_Event e) {
-  GuiButton* val = find_in_buttons_map(e->get_name());
-  if (val == (GuiButton *)NULL) {
-#ifdef _DEBUG
-    if (gui_cat.is_debug())
-      gui_cat.debug()
-	<< "Ignoring event " << e->get_name() << " for deleted button\n";
-#endif
-    return;
-  }
+  const MouseWatcherRegion* rgn = DCAST(MouseWatcherRegion, e->get_parameter(0).get_ptr());
+  GuiButton* val = find_in_buttons_set(rgn);
+  if (val == (GuiButton *)0L)
+    return;  // this one wasn't for us
   val->test_ref_count_integrity();
   val->down();
 }
 
 static void click_button_up(CPT_Event e) {
-  GuiButton* val = find_in_buttons_map(e->get_name());
-  if (val == (GuiButton *)NULL) {
-#ifdef _DEBUG
-    if (gui_cat.is_debug()) {
-      gui_cat.debug()
-	<< "Ignoring event " << e->get_name() << " for deleted button\n";
-    }
-#endif
-    return;
-  }
+  const MouseWatcherRegion* rgn = DCAST(MouseWatcherRegion, e->get_parameter(0).get_ptr());
+  GuiButton* val = find_in_buttons_set(rgn);
+  if (val == (GuiButton *)0L)
+    return;  // this one wasn't for us
   val->test_ref_count_integrity();
   val->up();
 }
 
 void GuiButton::switch_state(GuiButton::States nstate) {
   if (_mgr == (GuiManager*)0L) {
-    /*
-    gui_cat.warning()
-      << "Tried to switch state of unmanaged button\n";
-    */
     _state = nstate;
     return;
   }
 
   test_ref_count_integrity();
-  States ostate = _state;
   // cleanup old state
   switch (_state) {
   case NONE:
     break;
   case UP:
-    _mgr->remove_label(_up);
+    if (_mgr->has_label(_up))
+      _mgr->remove_label(_up);
     break;
   case UP_ROLLOVER:
-    _mgr->remove_label(_up_rollover);
+    if (_mgr->has_label(_up_rollover))
+      _mgr->remove_label(_up_rollover);
     break;
   case DOWN:
-    _mgr->remove_label(_down);
+    if (_mgr->has_label(_down))
+      _mgr->remove_label(_down);
     break;
   case DOWN_ROLLOVER:
-    _mgr->remove_label(_down_rollover);
+    if (_mgr->has_label(_down_rollover))
+      _mgr->remove_label(_down_rollover);
     break;
   case INACTIVE:
     if (_inactive != (GuiLabel*)0L)
-      _mgr->remove_label(_inactive);
+      if (_mgr->has_label(_inactive))
+	_mgr->remove_label(_inactive);
     break;
   case INACTIVE_ROLLOVER:
     if (_inactive != (GuiLabel*)0L)
-      _mgr->remove_label(_inactive);
+      if (_mgr->has_label(_inactive))
+	_mgr->remove_label(_inactive);
     break;
   default:
     gui_cat->warning() << "switching away from invalid state (" << (int)_state
@@ -159,119 +138,161 @@ void GuiButton::switch_state(GuiButton::States nstate) {
   // deal with new state
   switch (_state) {
   case NONE:
-    _rgn->trap_clicks(false);
+    if (_mgr->has_region(_rgn))
+      _mgr->remove_region(_rgn);
+    _rgn->set_suppress_below(false);
     break;
   case UP:
-    if (_alt_root.is_null())
-      _mgr->add_label(_up);
-    else
-      _mgr->add_label(_up, _alt_root);
+    if (!(_mgr->has_region(_rgn)))
+      _mgr->add_region(_rgn);
+    if (_alt_root.is_null()) {
+      if (!(_mgr->has_label(_up)))
+	_mgr->add_label(_up);
+    } else {
+      if (!(_mgr->has_label(_up)))
+	_mgr->add_label(_up, _alt_root);
+    }
     if (!_up_event.empty()) {
-#ifdef _DEBUG
-      gui_cat->debug() << "throwing _up_event '" << _up_event << "'" << endl;
-#endif
-      throw_event(_up_event);
-    } else 
+      if (gui_cat->is_debug())
+	gui_cat->debug() << "throwing _up_event '" << _up_event << "'" << endl;
+      throw_event(_up_event, EventParameter(this));
+    } else
+      if (gui_cat->is_debug())
 	gui_cat->debug() << "_up_event is empty!" << endl;
-    _rgn->trap_clicks(true);
-    if ((ostate == INACTIVE) || (ostate == INACTIVE_ROLLOVER))
-      _mgr->add_region(_rgn);
+    _rgn->set_suppress_below(true);
     break;
   case UP_ROLLOVER:
+    if (!(_mgr->has_region(_rgn)))
+      _mgr->add_region(_rgn);
     if (_up_rollover != (GuiLabel*)0L) {
-      if (_alt_root.is_null())
-	_mgr->add_label(_up_rollover);
-      else
-	_mgr->add_label(_up_rollover, _alt_root);
+      if (_alt_root.is_null()) {
+	if (!(_mgr->has_label(_up_rollover)))
+	  _mgr->add_label(_up_rollover);
+      } else {
+	if (!(_mgr->has_label(_up_rollover)))
+	  _mgr->add_label(_up_rollover, _alt_root);
+      }
       if (!_up_rollover_event.empty()) {
-#ifdef _DEBUG
-	gui_cat->debug() << "throwing _up_rollover_event '"
-			 << _up_rollover_event << "'" << endl;
-#endif
-	throw_event(_up_rollover_event);
-      } else 
-	gui_cat->debug() << "_up_rollover_event is empty!" << endl;
+	if (gui_cat->is_debug())
+	  gui_cat->debug() << "throwing _up_rollover_event '"
+			   << _up_rollover_event << "'" << endl;
+	throw_event(_up_rollover_event, EventParameter(this));
+      } else if (gui_cat->is_debug())
+	  gui_cat->debug() << "_up_rollover_event is empty!" << endl;
     } else {
-      if (_alt_root.is_null())
-	_mgr->add_label(_up);
-      else
-	_mgr->add_label(_up, _alt_root);
+      if (_alt_root.is_null()) {
+	if (!(_mgr->has_label(_up)))
+	  _mgr->add_label(_up);
+      } else {
+	if (!(_mgr->has_label(_up)))
+	  _mgr->add_label(_up, _alt_root);
+      }
       if (!_up_event.empty()) {
-#ifdef _DEBUG
-	gui_cat->debug() << "throwing _up_event '" << _up_event << "'" << endl;
-#endif
-	throw_event(_up_event);
-      } else
+	if (gui_cat->is_debug())
+	  gui_cat->debug() << "throwing _up_event '" << _up_event << "'"
+			   << endl;
+	throw_event(_up_event, EventParameter(this));
+      } else if (gui_cat->is_debug())
 	gui_cat->debug() << "_up_event is empty!" << endl;
       _state = UP;
     }
-    _rgn->trap_clicks(true);
-    if ((ostate == INACTIVE) || (ostate == INACTIVE_ROLLOVER))
-      _mgr->add_region(_rgn);
+    _rgn->set_suppress_below(true);
     break;
   case DOWN:
-    if (_alt_root.is_null())
-      _mgr->add_label(_down);
-    else
-      _mgr->add_label(_down, _alt_root);
-    if (!_down_event.empty())
-      throw_event(_down_event);
-    else
-      gui_cat->debug() << "_down_event is empty!" << endl;
-    _rgn->trap_clicks(true);
-    if ((ostate == INACTIVE) || (ostate == INACTIVE_ROLLOVER))
+    if (!(_mgr->has_region(_rgn)))
       _mgr->add_region(_rgn);
+    if (_alt_root.is_null()) {
+      if (!(_mgr->has_label(_down)))
+	_mgr->add_label(_down);
+    } else {
+      if (!(_mgr->has_label(_down)))
+	_mgr->add_label(_down, _alt_root);
+    }
+    if (!_down_event.empty()) {
+      if (gui_cat->is_debug())
+	gui_cat->debug() << "throwing _down_event '" << _down_event << "'"
+			 << endl;
+      throw_event(_down_event, EventParameter(this));
+    } else if (gui_cat->is_debug())
+      gui_cat->debug() << "_down_event is empty!" << endl;
+    _rgn->set_suppress_below(true);
     break;
   case DOWN_ROLLOVER:
+    if (!(_mgr->has_region(_rgn)))
+      _mgr->add_region(_rgn);
     if (_down_rollover != (GuiLabel*)0L) {
-      if (_alt_root.is_null())
-	_mgr->add_label(_down_rollover);
-      else
-	_mgr->add_label(_down_rollover, _alt_root);
-      if (!_down_rollover_event.empty())
-	throw_event(_down_rollover_event);
-      else
+      if (_alt_root.is_null()) {
+	if (!(_mgr->has_label(_down_rollover)))
+	  _mgr->add_label(_down_rollover);
+      } else {
+	if (!(_mgr->has_label(_down_rollover)))
+	  _mgr->add_label(_down_rollover, _alt_root);
+      }
+      if (!_down_rollover_event.empty()) {
+	if (gui_cat->is_debug())
+	  gui_cat->debug() << "throwing _down_rollover_event '"
+			   << _down_rollover_event << "'" << endl;
+	throw_event(_down_rollover_event, EventParameter(this));
+      } else if (gui_cat->is_debug())
 	gui_cat->debug() << "_down_rollover_event is empty!" << endl;
     } else {
-      if (_alt_root.is_null())
-	_mgr->add_label(_down);
-      else
-	_mgr->add_label(_down, _alt_root);
-      if (!_down_event.empty())
-	throw_event(_down_event);
-      else
+      if (_alt_root.is_null()) {
+	if (!(_mgr->has_label(_down)))
+	  _mgr->add_label(_down);
+      } else {
+	if (!(_mgr->has_label(_down)))
+	  _mgr->add_label(_down, _alt_root);
+      }
+      if (!_down_event.empty()) {
+	if (gui_cat->is_debug())
+	  gui_cat->debug() << "throwing _down_event '" << _down_event << "'"
+			   << endl;
+	throw_event(_down_event, EventParameter(this));
+      } else if (gui_cat->is_debug())
 	gui_cat->debug() << "_down_event is empty!" << endl;
       _state = DOWN;
     }
-    _rgn->trap_clicks(true);
-    if ((ostate == INACTIVE) || (ostate == INACTIVE_ROLLOVER))
-      _mgr->add_region(_rgn);
+    _rgn->set_suppress_below(true);
     break;
   case INACTIVE:
+    if (_mgr->has_region(_rgn))
+      _mgr->remove_region(_rgn);
     if (_inactive != (GuiLabel*)0L) {
-      if (_alt_root.is_null())
-	_mgr->add_label(_inactive);
-      else
-	_mgr->add_label(_inactive, _alt_root);
-      if (!_inactive_event.empty())
-	throw_event(_inactive_event);
+      if (_alt_root.is_null()) {
+	if (!(_mgr->has_label(_inactive)))
+	  _mgr->add_label(_inactive);
+      } else {
+	if (!(_mgr->has_label(_inactive)))
+	  _mgr->add_label(_inactive, _alt_root);
+      }
+      if (!_inactive_event.empty()) {
+	if (gui_cat->is_debug())
+	  gui_cat->debug() << "throwing _inactive_event '" << _inactive_event
+			   << "'" << endl;
+	throw_event(_inactive_event, EventParameter(this));
+      }
     }
-    _rgn->trap_clicks(false);
-    if ((ostate != INACTIVE) && (ostate != INACTIVE_ROLLOVER))
-      _mgr->remove_region(_rgn);
+    _rgn->set_suppress_below(false);
     break;
   case INACTIVE_ROLLOVER:
+    if (_mgr->has_region(_rgn))
+      _mgr->remove_region(_rgn);
     if (_inactive != (GuiLabel*)0L) {
-      if (_alt_root.is_null())
-	_mgr->add_label(_inactive);
-      else
-	_mgr->add_label(_inactive, _alt_root);
-      if (!_inactive_event.empty())
-	throw_event(_inactive_event);
+      if (_alt_root.is_null()) {
+	if (!(_mgr->has_label(_inactive)))
+	  _mgr->add_label(_inactive);
+      } else {
+	if (!(_mgr->has_label(_inactive)))
+	  _mgr->add_label(_inactive, _alt_root);
+      }
+      if (!_inactive_event.empty()) {
+	if (gui_cat->is_debug())
+	  gui_cat->debug() << "throwing _inactive_event '" << _inactive_event
+			   << "'" << endl;
+	throw_event(_inactive_event, EventParameter(this));
+      }
     }
-    _rgn->trap_clicks(false);
-    if ((ostate != INACTIVE) && (ostate != INACTIVE_ROLLOVER))
-      _mgr->remove_region(_rgn);
+    _rgn->set_suppress_below(false);
     break;
   default:
     gui_cat->warning() << "switched to invalid state (" << (int)_state << ")"
@@ -297,7 +318,7 @@ void GuiButton::adjust_region(void) {
   GetExtents(_up, _down, _up_rollover, _down_rollover, _inactive, _left,
 	     _right, _bottom, _top);
   GuiBehavior::adjust_region();
-  _rgn->set_region(_left, _right, _bottom, _top);
+  _rgn->set_frame(_left, _right, _bottom, _top);
 }
 
 void GuiButton::set_priority(GuiLabel* l, GuiItem::Priority p) {
@@ -315,112 +336,105 @@ void GuiButton::set_priority(GuiLabel* l, GuiItem::Priority p) {
   GuiItem::set_priority(l, p);
 }
 
-void GuiButton::behavior_up(CPT_Event, void* data) {
-  GuiButton* button = (GuiButton*)data;
-#ifdef _DEBUG
-  gui_cat->debug() << "behavior_up (0x" << data << ")" << endl;
-#endif
+void GuiButton::behavior_up(CPT_Event e) {
+  const GuiButton* button = DCAST(GuiButton, e->get_parameter(0).get_ptr());
+  if (gui_cat->is_debug())
+    gui_cat->debug() << "behavior_up (0x" << (void*)button << ")" << endl;
   button->run_button_up();
 }
 
-void GuiButton::behavior_down(CPT_Event, void* data) {
-  GuiButton* button = (GuiButton*)data;
-#ifdef _DEBUG
-  gui_cat->debug() << "behavior_down (0x" << data << ")" << endl;
-#endif
+void GuiButton::behavior_down(CPT_Event e) {
+  const GuiButton* button = DCAST(GuiButton, e->get_parameter(0).get_ptr());
+  if (gui_cat->is_debug())
+    gui_cat->debug() << "behavior_down (0x" << (void*)button << ")" << endl;
   button->run_button_down();
 }
 
-void GuiButton::run_button_up(void) {
-#ifdef _DEBUG
-  gui_cat->debug() << "run_button_up (0x" << (void*)this << " '" << this->get_name()
-       << "')" << endl;
-#endif
-  if (_eh == (EventHandler*)0L)
+void GuiButton::run_button_up(void) const {
+  if (gui_cat->is_debug())
+    gui_cat->debug() << "run_button_up (0x" << (void*)this << " '"
+		     << this->get_name() << "')" << endl;
+  if ((_eh == (EventHandler*)0L) || (!(this->_behavior_running)))
     return;
-#ifdef _DEBUG
-  gui_cat->debug() << "doing work" << endl;
-#endif
-  _eh->remove_hook(_up_event, GuiButton::behavior_up, (void*)this);
-  _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
+  if (gui_cat->is_debug())
+    gui_cat->debug() << "doing work" << endl;
+  _eh->remove_hook(_up_event, GuiButton::behavior_up);
+  _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up);
   if (!_behavior_event.empty()) {
-    if (_have_event_param)
-      throw_event(_behavior_event, EventParameter(_event_param));
-    else
-      throw_event(_behavior_event);
+    if (_have_event_param) {
+      if (gui_cat->is_debug())
+	gui_cat->debug() << "throwing behavior event '" << _behavior_event
+			 << "' with parameter (" << _event_param << ")"
+			 << endl;
+      throw_event(_behavior_event, EventParameter(this),
+		  EventParameter(_event_param));
+    } else {
+      if (gui_cat->is_debug())
+	gui_cat->debug() << "throwing behavior event '" << _behavior_event
+			 << "'" << endl;
+      throw_event(_behavior_event, EventParameter(this));
+    }
   }
   if (_behavior_functor != (GuiBehavior::BehaviorFunctor*)0L)
-    _behavior_functor->doit(this);
+    _behavior_functor->doit((GuiBehavior*)this);
 }
 
-void GuiButton::run_button_down(void) {
-#ifdef _DEBUG
-  gui_cat->debug() << "run_button_down (0x" << (void*)this << " '" << this->get_name()
-       << "')" << endl;
-#endif
-  if (_eh == (EventHandler*)0L)
+void GuiButton::run_button_down(void) const {
+  if (gui_cat->is_debug())
+    gui_cat->debug() << "run_button_down (0x" << (void*)this << " '"
+		     << this->get_name() << "')" << endl;
+  if ((_eh == (EventHandler*)0L) || (!(this->_behavior_running)))
     return;
-#ifdef _DEBUG
-  gui_cat->debug() << "doing work, up_event is '" << _up_event << "' '"
-       << _up_rollover_event << "'" << endl;
-#endif
-  _eh->add_hook(_up_event, GuiButton::behavior_up, (void*)this);
-  _eh->add_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
+  if (gui_cat->is_debug())
+    gui_cat->debug() << "doing work, up_event is '" << _up_event << "' '"
+		     << _up_rollover_event << "'" << endl;
+  _eh->add_hook(_up_event, GuiButton::behavior_up);
+  _eh->add_hook(_up_rollover_event, GuiButton::behavior_up);
 }
 
 GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* down)
   : GuiBehavior(name), _up(up), _up_rollover((GuiLabel*)0L), _down(down),
     _down_rollover((GuiLabel*)0L), _inactive((GuiLabel*)0L),
-    _up_event(name + "-up"), _up_rollover_event(""),
-    _down_event(name +"-down"), _down_rollover_event(""),
+    _up_event("GuiButton-up"), _up_rollover_event(""),
+    _down_event("GuiButton-down"), _down_rollover_event(""),
     _inactive_event(""), _up_scale(up->get_scale()), _upr_scale(1.),
     _down_scale(down->get_scale()), _downr_scale(1.), _inactive_scale(1.),
     _state(GuiButton::NONE), _have_event_param(false), _event_param(0),
     _behavior_functor((GuiBehavior::BehaviorFunctor*)0L) {
   GetExtents(up, down, _up_rollover, _down_rollover, _inactive, _left, _right,
 	     _bottom, _top);
-  _rgn = new GuiRegion("button-" + name, _left, _right, _bottom, _top, true);
-  buttons["gui-in-button-" + name] = this;
-  buttons["gui-out-button-" + name] = this;
-  buttons["gui-button-" + name + "-mouse1"] = this;
-  buttons["gui-button-" + name + "-mouse2"] = this;
-  buttons["gui-button-" + name + "-mouse3"] = this;
-  buttons["gui-button-" + name + "-mouse1-up"] = this;
-  buttons["gui-button-" + name + "-mouse2-up"] = this;
-  buttons["gui-button-" + name + "-mouse3-up"] = this;
+  _rgn = new MouseWatcherRegion("button-" + name, _left, _right, _bottom,
+				_top);
+  _rgn->set_suppress_below(true);
+  buttons.insert(this);
 }
 
 GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* down,
 		     GuiLabel* inactive)
   : GuiBehavior(name), _up(up), _up_rollover((GuiLabel*)0L), _down(down),
     _down_rollover((GuiLabel*)0L), _inactive(inactive),
-    _up_event(name + "-up"), _up_rollover_event(""),
-    _down_event(name +"-down"), _down_rollover_event(""),
-    _inactive_event(name + "-inactive"), _up_scale(up->get_scale()),
+    _up_event("GuiButton-up"), _up_rollover_event(""),
+    _down_event("GuiButton-down"), _down_rollover_event(""),
+    _inactive_event("GuiButton-inactive"), _up_scale(up->get_scale()),
     _upr_scale(1.), _down_scale(down->get_scale()), _downr_scale(1.),
     _inactive_scale(inactive->get_scale()), _state(GuiButton::NONE),
     _have_event_param(false), _event_param(0),
     _behavior_functor((GuiBehavior::BehaviorFunctor*)0L) {
   GetExtents(up, down, _up_rollover, _down_rollover, inactive, _left, _right,
 	     _bottom, _top);
-  _rgn = new GuiRegion("button-" + name, _left, _right, _bottom, _top, true);
-  buttons["gui-in-button-" + name] = this;
-  buttons["gui-out-button-" + name] = this;
-  buttons["gui-button-" + name + "-mouse1"] = this;
-  buttons["gui-button-" + name + "-mouse2"] = this;
-  buttons["gui-button-" + name + "-mouse3"] = this;
-  buttons["gui-button-" + name + "-mouse1-up"] = this;
-  buttons["gui-button-" + name + "-mouse2-up"] = this;
-  buttons["gui-button-" + name + "-mouse3-up"] = this;
+  _rgn = new MouseWatcherRegion("button-" + name, _left, _right, _bottom,
+				_top);
+  _rgn->set_suppress_below(true);
+  buttons.insert(this);
 }
 
 GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* up_roll,
 		     GuiLabel* down, GuiLabel* down_roll, GuiLabel* inactive)
   : GuiBehavior(name), _up(up), _up_rollover(up_roll), _down(down),
-    _down_rollover(down_roll), _inactive(inactive), _up_event(name + "-up"),
-    _up_rollover_event(name + "-up-rollover"), _down_event(name +"-down"),
-    _down_rollover_event(name + "-down-rollover"),
-    _inactive_event(name + "-inactive"), _up_scale(up->get_scale()),
+    _down_rollover(down_roll), _inactive(inactive), _up_event("GuiButton-up"),
+    _up_rollover_event("GuiButton-up-rollover"), _down_event("GuiButton-down"),
+    _down_rollover_event("GuiButton-down-rollover"),
+    _inactive_event("GuiButton-inactive"), _up_scale(up->get_scale()),
     _upr_scale(up_roll->get_scale()), _down_scale(down->get_scale()),
     _downr_scale(down_roll->get_scale()),
     _inactive_scale(inactive->get_scale()), _state(GuiButton::NONE),
@@ -428,15 +442,10 @@ GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* up_roll,
     _behavior_functor((GuiBehavior::BehaviorFunctor*)0L) {
   GetExtents(up, down, up_roll, down_roll, inactive, _left, _right, _bottom,
 	     _top);
-  _rgn = new GuiRegion("button-" + name, _left, _right, _bottom, _top, true);
-  buttons["gui-in-button-" + name] = this;
-  buttons["gui-out-button-" + name] = this;
-  buttons["gui-button-" + name + "-mouse1"] = this;
-  buttons["gui-button-" + name + "-mouse2"] = this;
-  buttons["gui-button-" + name + "-mouse3"] = this;
-  buttons["gui-button-" + name + "-mouse1-up"] = this;
-  buttons["gui-button-" + name + "-mouse2-up"] = this;
-  buttons["gui-button-" + name + "-mouse3-up"] = this;
+  _rgn = new MouseWatcherRegion("button-" + name, _left, _right, _bottom,
+				_top);
+  _rgn->set_suppress_below(true);
+  buttons.insert(this);
 }
 
 GuiButton::~GuiButton(void) {
@@ -445,33 +454,28 @@ GuiButton::~GuiButton(void) {
   // 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");
-  buttons.erase("gui-button-" + name + "-mouse1-up");
-  buttons.erase("gui-button-" + name + "-mouse2-up");
-  buttons.erase("gui-button-" + name + "-mouse3-up");
+  buttons.erase(this);
+  if ((buttons.size() == 0) && added_hooks) {
+    _eh->remove_hook("gui-enter", enter_button);
+    _eh->remove_hook("gui-exit" + get_name(), exit_button);
+    _eh->remove_hook("gui-button-press", click_button_down);
+    _eh->remove_hook("gui-button-release", click_button_up);
+    added_hooks = false;
+  }
 
   if (_behavior_functor != (GuiBehavior::BehaviorFunctor*)0L)
     delete _behavior_functor;
 }
 
 void GuiButton::manage(GuiManager* mgr, EventHandler& eh) {
-  if (!_added_hooks) {
-    eh.add_hook("gui-in-button-" + get_name(), enter_button);
-    eh.add_hook("gui-out-button-" + get_name(), exit_button);
-    eh.add_hook("gui-button-" + get_name() + "-mouse1", click_button_down);
-    eh.add_hook("gui-button-" + get_name() + "-mouse2", click_button_down);
-    eh.add_hook("gui-button-" + get_name() + "-mouse3", click_button_down);
-    eh.add_hook("gui-button-" + get_name() + "-mouse1-up", click_button_up);
-    eh.add_hook("gui-button-" + get_name() + "-mouse2-up", click_button_up);
-    eh.add_hook("gui-button-" + get_name() + "-mouse3-up", click_button_up);
-    _added_hooks = true;
+  if (!added_hooks) {
+    eh.add_hook("gui-enter", enter_button);
+    eh.add_hook("gui-exit", exit_button);
+    eh.add_hook("gui-button-press", click_button_down);
+    eh.add_hook("gui-button-release", click_button_up);
+    added_hooks = true;
   }
   if (_mgr == (GuiManager*)0L) {
-    mgr->add_region(_rgn);
     GuiBehavior::manage(mgr, eh);
     if (_behavior_running)
       this->start_behavior();
@@ -482,19 +486,14 @@ void GuiButton::manage(GuiManager* mgr, EventHandler& eh) {
 }
 
 void GuiButton::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
-  if (!_added_hooks) {
-    eh.add_hook("gui-in-button-" + get_name(), enter_button);
-    eh.add_hook("gui-out-button-" + get_name(), exit_button);
-    eh.add_hook("gui-button-" + get_name() + "-mouse1", click_button_down);
-    eh.add_hook("gui-button-" + get_name() + "-mouse2", click_button_down);
-    eh.add_hook("gui-button-" + get_name() + "-mouse3", click_button_down);
-    eh.add_hook("gui-button-" + get_name() + "-mouse1-up", click_button_up);
-    eh.add_hook("gui-button-" + get_name() + "-mouse2-up", click_button_up);
-    eh.add_hook("gui-button-" + get_name() + "-mouse3-up", click_button_up);
-    _added_hooks = true;
+  if (!added_hooks) {
+    eh.add_hook("gui-enter", enter_button);
+    eh.add_hook("gui-exit", exit_button);
+    eh.add_hook("gui-button-press", click_button_down);
+    eh.add_hook("gui-button-release", click_button_up);
+    added_hooks = true;
   }
   if (_mgr == (GuiManager*)0L) {
-    mgr->add_region(_rgn);
     GuiBehavior::manage(mgr, eh, n);
     if (_behavior_running)
       this->start_behavior();
@@ -506,8 +505,7 @@ void GuiButton::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
 
 void GuiButton::unmanage(void) {
   if (_mgr != (GuiManager*)0L)
-    if ((_state != NONE) && (_state != INACTIVE) &&
-	(_state != INACTIVE_ROLLOVER))
+    if (_mgr->has_region(_rgn))
       _mgr->remove_region(_rgn);
   if (_behavior_running)
     this->stop_behavior();
@@ -586,31 +584,29 @@ void GuiButton::start_behavior(void) {
     return;
   if (!this->is_active())
     return;
-  _eh->add_hook(_down_event, GuiButton::behavior_down, (void*)this);
-  _eh->add_hook(_down_rollover_event, GuiButton::behavior_down, (void*)this);
+  _eh->add_hook(_down_event, GuiButton::behavior_down);
+  _eh->add_hook(_down_rollover_event, GuiButton::behavior_down);
 }
 
 void GuiButton::stop_behavior(void) {
   GuiBehavior::stop_behavior();
   if (_mgr == (GuiManager*)0L)
     return;
-  _eh->remove_hook(_up_event, GuiButton::behavior_up, (void*)this);
-  _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
-  _eh->remove_hook(_down_event, GuiButton::behavior_down, (void*)this);
-  _eh->remove_hook(_down_rollover_event, GuiButton::behavior_down,
-		   (void*)this);
+  _eh->remove_hook(_up_event, GuiButton::behavior_up);
+  _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up);
+  /*
+  _eh->remove_hook(_down_event, GuiButton::behavior_down);
+  _eh->remove_hook(_down_rollover_event, GuiButton::behavior_down);
+  */
 }
 
 void GuiButton::reset_behavior(void) {
-#ifdef _DEBUG
-  gui_cat->debug() << this->get_name() << "::reset_behavior()" << endl;
-#endif
   GuiBehavior::reset_behavior();
   if (_mgr == (GuiManager*)0L)
     return;
   this->start_behavior();
-  _eh->remove_hook(_up_event, GuiButton::behavior_up, (void*)this);
-  _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
+  _eh->remove_hook(_up_event, GuiButton::behavior_up);
+  _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up);
 }
 
 void GuiButton::set_priority(GuiItem* i, const GuiItem::Priority p) {
@@ -650,7 +646,8 @@ int GuiButton::set_draw_order(int v) {
   // there's no need to cascade the draw orders.  They can each be
   // assigned the same value, and the value we return is the maximum
   // of any of the values returned by the labels.
-  int o = _rgn->set_draw_order(v);
+  _rgn->set_sort(v);
+  int o = v+1;
   int o1 = _up->set_draw_order(v);
   o = max(o, o1);
   o1 = _down->set_draw_order(v);
@@ -685,7 +682,9 @@ void GuiButton::output(ostream& os) const {
   os << "    down event - '" << _down_event << "'" << endl;
   os << "    down_rollover event - '" << _down_rollover_event << "'" << endl;
   os << "    inactive event - '" << _inactive_event << "'" << endl;
-  os << "    rgn - 0x" << (void*)_rgn << endl;
+  os << "    behavior event - '" << _behavior_event << "'" << endl;
+  os << "    behavior param - " << _event_param << "'" << endl;
+  os << "    rgn - 0x" << (void*)_rgn << " (" << *_rgn << ")" << endl;
   os << "      frame - " << _rgn->get_frame() << endl;
   os << "    state - " << (int)_state << endl;
 }

+ 9 - 6
panda/src/gui/guiButton.h

@@ -7,10 +7,11 @@
 #define __GUIBUTTON_H__
 
 #include "guiBehavior.h"
-#include "guiRegion.h"
 #include "guiLabel.h"
 #include "guiManager.h"
 
+#include <mouseWatcherRegion.h>
+
 class EXPCL_PANDA GuiButton : public GuiBehavior {
 private:
   PT(GuiLabel) _up;
@@ -20,7 +21,7 @@ private:
   PT(GuiLabel) _inactive;
   string _up_event, _up_rollover_event, _down_event, _down_rollover_event;
   string _inactive_event;
-  PT(GuiRegion) _rgn;
+  PT(MouseWatcherRegion) _rgn;
 
   float _up_scale;
   float _upr_scale;
@@ -42,10 +43,10 @@ private:
   virtual void recompute_frame(void);
   virtual void adjust_region(void);
 
-  static void behavior_up(CPT_Event, void*);
-  static void behavior_down(CPT_Event, void*);
-  void run_button_up(void);
-  void run_button_down(void);
+  static void behavior_up(CPT_Event);
+  static void behavior_down(CPT_Event);
+  void run_button_up(void) const;
+  void run_button_down(void) const;
 PUBLISHED:
   GuiButton(const string&, GuiLabel*, GuiLabel*);
   GuiButton(const string&, GuiLabel*, GuiLabel*, GuiLabel*);
@@ -58,6 +59,8 @@ public:
   virtual void manage(GuiManager*, EventHandler&, Node*);
   virtual void unmanage(void);
 
+  INLINE bool owns_region(const MouseWatcherRegion*) const;
+
 PUBLISHED:
   virtual int freeze();
   virtual int thaw();

+ 0 - 4
panda/src/gui/guiCollection.cxx

@@ -74,8 +74,6 @@ void GuiCollection::remove_item(GuiItem* item) {
 }
 
 void GuiCollection::manage(GuiManager* mgr, EventHandler& eh) {
-  if (!_added_hooks)
-    _added_hooks = true;
   if (_mgr == (GuiManager*)0L) {
     for (Items::iterator i=_items.begin(); i!=_items.end(); ++i)
       (*i)->manage(mgr, eh);
@@ -86,8 +84,6 @@ void GuiCollection::manage(GuiManager* mgr, EventHandler& eh) {
 }
 
 void GuiCollection::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
-  if (!_added_hooks)
-    _added_hooks = true;
   if (_mgr == (GuiManager*)0L) {
     for (Items::iterator i=_items.begin(); i!=_items.end(); ++i)
       (*i)->manage(mgr, eh, n);

+ 1 - 7
panda/src/gui/guiFrame.cxx

@@ -321,9 +321,6 @@ void GuiFrame::clear_all_packing(void) {
 }
 
 void GuiFrame::manage(GuiManager* mgr, EventHandler& eh) {
-  if (!_added_hooks) {
-    _added_hooks = true;
-  }
   if (_mgr == (GuiManager*)0L) {
     for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i)
       (*i).get_item()->manage(mgr, eh);
@@ -334,9 +331,6 @@ void GuiFrame::manage(GuiManager* mgr, EventHandler& eh) {
 }
 
 void GuiFrame::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
-  if (!_added_hooks) {
-    _added_hooks = true;
-  }
   if (_mgr == (GuiManager*)0L) {
     for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i)
       (*i).get_item()->manage(mgr, eh, n);
@@ -384,7 +378,7 @@ void GuiFrame::set_priority(GuiItem* it, const GuiItem::Priority p) {
 }
 
 int GuiFrame::set_draw_order(int v) {
-  int o;
+  int o = v;
   bool first = true;
   for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i)
     if (first) {

+ 5 - 7
panda/src/gui/guiItem.cxx

@@ -36,12 +36,11 @@ void GuiItem::adjust_region(void) {
 void GuiItem::set_priority(GuiLabel*, const GuiItem::Priority) {
 }
 
-GuiItem::GuiItem(const string& name) : Namable(name), _added_hooks(false),
-				       _scale(1.), _scale_x(1.), _scale_y(1.),
-				       _scale_z(1.), _left(-1.), _right(1.),
-				       _bottom(-1.), _top(1.),
-				       _pos(0., 0., 0.),
-				       _mgr((GuiManager*)0L), _pri(P_Normal) {
+GuiItem::GuiItem(const string& name) : Namable(name), _scale(1.), _scale_x(1.),
+				       _scale_y(1.), _scale_z(1.), _left(-1.),
+				       _right(1.), _bottom(-1.), _top(1.),
+				       _pos(0., 0., 0.), _mgr((GuiManager*)0L),
+				       _pri(P_Normal) {
 
   if (gui_cat->is_debug())
     gui_cat->debug()
@@ -108,7 +107,6 @@ int GuiItem::set_draw_order(int v) {
 void GuiItem::output(ostream& os) const {
   os << "GuiItem (0x" << (void*)this << ")" << endl;
   os << "  name - '" << get_name() << "'" << endl;
-  os << "  hooks have" << (_added_hooks?" ":" not ") << "been added" << endl;
   os << "  scale - " << _scale << endl;
   os << "  pos - " << _pos << endl;
   os << "  mgr - 0x" << (void*)_mgr << endl;

+ 0 - 1
panda/src/gui/guiItem.h

@@ -15,7 +15,6 @@ PUBLISHED:
   enum Priority { P_Lowest, P_Low, P_Normal, P_High, P_Highest };
 
 protected:
-  bool _added_hooks;
   float _scale, _scale_x, _scale_y, _scale_z, _left, _right, _bottom, _top;
   LVector3f _pos;
   GuiManager* _mgr;

+ 31 - 36
panda/src/gui/guiManager.cxx

@@ -22,27 +22,21 @@ GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak,
 				Node *root2d) {
   GuiManager* ret;
   if (_map == (GuiMap*)0L) {
-#ifdef _DEBUG
     if (gui_cat->is_debug())
       gui_cat->debug() << "allocating a manager map" << endl;
-#endif
     _map = new GuiMap;
   }
   GuiMap::const_iterator gi;
   gi = _map->find(w);
   if (gi != _map->end()) {
     ret = (*gi).second;
-#ifdef _DEBUG
     if (gui_cat->is_debug())
       gui_cat->debug() << "a manager for this window already exists (0x"
 		       << (void*)ret << ")" << endl;
-#endif
   } else {
     // going to allocate a new GuiManager for this window
-#ifdef _DEBUG
     if (gui_cat->is_debug())
       gui_cat->debug() << "allocating a new manager for this window" << endl;
-#endif
     // first see if there is a mouseWatcher already under the MouseAndKeyboard
     bool has_watcher = false;
     TypeHandle dgt = DataRelation::get_class_type();
@@ -56,10 +50,8 @@ GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak,
     if (!has_watcher) {
       // there isn't already a mousewatcher in the data graph, so we'll make
       // one and re-parent everything to it.
-#ifdef _DEBUG
       if (gui_cat->is_debug())
 	gui_cat->debug() << "no MouseWatcher found, making one" << endl;
-#endif
       watcher = new MouseWatcher("GUI watcher");
       DataRelation* tmp = new DataRelation(mak, watcher);
       for (int j=0; j<mak->get_num_children(dgt); ++j) {
@@ -74,33 +66,26 @@ GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak,
 		       << endl;
     }
     // now setup event triggers for the watcher
-#ifdef _DEBUG
-    if (has_watcher && !watcher->get_button_down_pattern().empty()) {
+    if (has_watcher && !watcher->get_button_down_pattern().empty())
       gui_cat->warning() << "overwriting existing button down pattern '"
 			 << watcher->get_button_down_pattern()
-			 << "' with 'gui-%r-%b'" << endl;
-    }
-    if (has_watcher && !watcher->get_button_up_pattern().empty()) {
+			 << "' with 'gui-button-press'" << endl;
+    watcher->set_button_down_pattern("gui-button-press");
+    if (has_watcher && !watcher->get_button_up_pattern().empty())
       gui_cat->warning() << "overwriting existing button up pattern '"
 			 << watcher->get_button_up_pattern()
-			 << "' with 'gui-%r-%b-up'" << endl;
-    }
-    if (has_watcher && !watcher->get_enter_pattern().empty()) {
+			 << "' with 'gui-button-release'" << endl;
+    watcher->set_button_up_pattern("gui-button-release");
+    if (has_watcher && !watcher->get_enter_pattern().empty())
       gui_cat->warning() << "overwriting existing enter pattern '"
 			 << watcher->get_enter_pattern()
-			 << "' with 'gui-in-%r'" << endl;
-    }
-
-    if (has_watcher && !watcher->get_leave_pattern().empty()) {
+			 << "' with 'gui-enter'" << endl;
+    watcher->set_enter_pattern("gui-enter");
+    if (has_watcher && !watcher->get_leave_pattern().empty())
       gui_cat->warning() << "overwriting existing exit pattern '"
 			 << watcher->get_leave_pattern()
-			 << "' with 'gui-out-%r'" << endl;
-    }
-#endif
-    watcher->set_button_down_pattern("gui-%r-%b");
-    watcher->set_button_up_pattern("gui-%r-%b-up");
-    watcher->set_enter_pattern("gui-in-%r");
-    watcher->set_leave_pattern("gui-out-%r");
+			 << "' with 'gui-exit'" << endl;
+    watcher->set_leave_pattern("gui-exit");
 
     if (root2d == (Node *)NULL) {
       // If we weren't given a 2-d scene graph, then create one now.
@@ -127,30 +112,26 @@ GuiManager* GuiManager::get_ptr(GraphicsWindow* w, MouseAndKeyboard* mak,
       DisplayRegion *dr = layer->make_display_region();
       nassertr(dr != (DisplayRegion*)0L, NULL);
       dr->set_camera(cam);
-#ifdef _DEBUG
       if (gui_cat->is_debug())
 	gui_cat->debug() << "2D layer created" << endl;
-#endif
     }
 
     // now make the manager for this window
     ret = new GuiManager(watcher, root2d);
-#ifdef _DEBUG
     if (gui_cat->is_debug())
       gui_cat->debug() << "new manager allocated (0x" << (void*)ret << ")"
 		       << endl;
-#endif
     (*_map)[w] = ret;
   }
   return ret;
 }
 
-void GuiManager::add_region(GuiRegion* region) {
+void GuiManager::add_region(MouseWatcherRegion* region) {
   region->test_ref_count_integrity();
   RegionSet::const_iterator ri;
   ri = _regions.find(region);
   if (ri == _regions.end()) {
-    _watcher->add_region(region->get_region());
+    _watcher->add_region(region);
     _regions.insert(region);
   } else
     gui_cat->warning() << "tried adding region ('" << *region
@@ -183,7 +164,7 @@ void GuiManager::add_label(GuiLabel* label, Node* parent) {
 		       << ") more then once" << endl;
 }
 
-void GuiManager::remove_region(GuiRegion* region) {
+void GuiManager::remove_region(MouseWatcherRegion* region) {
   region->test_ref_count_integrity();
   RegionSet::iterator ri;
   ri = _regions.find(region);
@@ -191,7 +172,7 @@ void GuiManager::remove_region(GuiRegion* region) {
     gui_cat->warning() << "tried removing region ('" << *region
 		       << "') that isn't there" << endl;
   else {
-    _watcher->remove_region(region->get_region());
+    _watcher->remove_region(region);
     _regions.erase(ri);
   }
 }
@@ -211,6 +192,20 @@ void GuiManager::remove_label(GuiLabel* label) {
   }
 }
 
+bool GuiManager::has_region(MouseWatcherRegion* rgn) {
+  rgn->test_ref_count_integrity();
+  RegionSet::iterator ri;
+  ri = _regions.find(rgn);
+  return (ri != _regions.end());
+}
+
+bool GuiManager::has_label(GuiLabel* lbl) {
+  lbl->test_ref_count_integrity();
+  LabelSet::iterator li;
+  li = _labels.find(lbl);
+  return (li != _labels.end());
+}
+
 void GuiManager::recompute_priorities(void) {
   _sorts.clear();
   for (LabelSet::iterator i=_labels.begin(); i!=_labels.end(); ++i)
@@ -227,7 +222,7 @@ INLINE bool in_range(float x, float a, float b) {
   return ((x >= a) && (x <= b));
 }
 
-INLINE bool overlap(GuiRegion* a, GuiRegion* b) {
+INLINE bool overlap(MouseWatcherRegion* a, MouseWatcherRegion* b) {
   LVector4f av = a->get_frame();
   LVector4f bv = b->get_frame();
 

+ 7 - 4
panda/src/gui/guiManager.h

@@ -10,10 +10,10 @@
 #include <graphicsWindow.h>
 #include <mouse.h>
 #include <mouseWatcher.h>
+#include <mouseWatcherRegion.h>
 #include <node.h>
 #include <set>
 
-#include "guiRegion.h"
 #include "guiLabel.h"
 #include "config_gui.h"
 
@@ -21,7 +21,7 @@ class EXPCL_PANDA GuiManager {
 private:
   typedef map<GraphicsWindow*, GuiManager*> GuiMap;
   static GuiMap* _map;
-  typedef set<GuiRegion*> RegionSet;
+  typedef set<MouseWatcherRegion*> RegionSet;
   RegionSet _regions;
   typedef set<GuiLabel*> LabelSet;
   LabelSet _labels;
@@ -44,13 +44,16 @@ private:
 PUBLISHED:
   static GuiManager* get_ptr(GraphicsWindow*, MouseAndKeyboard*, Node *root2d);
 
-  void add_region(GuiRegion*);
+  void add_region(MouseWatcherRegion*);
   void add_label(GuiLabel*);
   void add_label(GuiLabel*, Node*);
 
-  void remove_region(GuiRegion*);
+  void remove_region(MouseWatcherRegion*);
   void remove_label(GuiLabel*);
 
+  bool has_region(MouseWatcherRegion*);
+  bool has_label(GuiLabel*);
+
   void recompute_priorities(void);
 
   INLINE int get_next_draw_order(void) const;

+ 1 - 4
panda/src/gui/guiRegion.h

@@ -17,11 +17,8 @@
 
 class GuiManager;
 
-class EXPCL_PANDA GuiRegion : public TypedReferenceCount, public Namable {
+class EXPCL_PANDA GuiRegion : public MouseWatcherRegion {
 private:
-  float _left, _right, _bottom, _top;
-  PT(MouseWatcherRegion) _region;
-
   INLINE GuiRegion(void);
 
   INLINE MouseWatcherRegion* get_region(void) const;

+ 4 - 0
panda/src/gui/guiRollover.I

@@ -43,3 +43,7 @@ INLINE void GuiRollover::exit(void) {
 INLINE bool GuiRollover::is_over(void) const {
   return _state;
 }
+
+INLINE bool GuiRollover::owns_region(const MouseWatcherRegion* rgn) const {
+  return (_rgn == rgn);
+}

+ 64 - 58
panda/src/gui/guiRollover.cxx

@@ -6,22 +6,21 @@
 #include "guiRollover.h"
 #include "config_gui.h"
 
-#include <map>
+#include <set>
 
-typedef map<string, GuiRollover*> RolloverMap;
-static RolloverMap rollovers;
+typedef set<GuiRollover*> RolloverSet;
+static RolloverSet rollovers;
+static bool added_hooks = false;
 
 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;
+find_in_rollovers_set(const MouseWatcherRegion* rgn) {
+  for (RolloverSet::const_iterator bi=rollovers.begin(); bi!=rollovers.end();
+       ++bi)
+    if ((*bi)->owns_region(rgn))
+      return *bi;
+  return (GuiRollover*)0L;
 }
 
 inline void GetExtents(GuiLabel* x, GuiLabel* y, float& l, float& r, float& b,
@@ -36,33 +35,23 @@ inline void GetExtents(GuiLabel* x, GuiLabel* y, float& l, float& r, float& b,
 }
 
 static void enter_rollover(CPT_Event e) {
-  GuiRollover* val = find_in_rollovers_map(e->get_name());
-  if (val == (GuiRollover *)NULL) {
-#ifdef _DEBUG
-    if (gui_cat.is_debug())
-      gui_cat.debug()
-	<< "Ignoring event " << e->get_name() << " for deleted rollover\n";
-#endif
-    return;
-  }
+  const MouseWatcherRegion* rgn = DCAST(MouseWatcherRegion, e->get_parameter(0).get_ptr());
+  GuiRollover* val = find_in_rollovers_set(rgn);
+  if (val == (GuiRollover *)0L)
+    return;  // this wasn't for us
   val->enter();
 }
 
 static void exit_rollover(CPT_Event e) {
-  GuiRollover* val = find_in_rollovers_map(e->get_name());
-  if (val == (GuiRollover *)NULL) {
-#ifdef _DEBUG
-    if (gui_cat.is_debug())
-      gui_cat.debug()
-	<< "Ignoring event " << e->get_name() << " for deleted rollover\n";
-#endif
-    return;
-  }
+  const MouseWatcherRegion* rgn = DCAST(MouseWatcherRegion, e->get_parameter(0).get_ptr());
+  GuiRollover* val = find_in_rollovers_set(rgn);
+  if (val == (GuiRollover *)0L)
+    return;  // this wasn't for us
   val->exit();
 }
 
 void GuiRollover::recompute_frame(void) {
-  GuiItem::recompute_frame();
+  GuiBehavior::recompute_frame();
   _off->recompute();
   _on->recompute();
   this->adjust_region();
@@ -70,24 +59,24 @@ void GuiRollover::recompute_frame(void) {
 
 void GuiRollover::adjust_region(void) {
   GetExtents(_off, _on, _left, _right, _bottom, _top);
-  GuiItem::adjust_region();
-  _rgn->set_region(_left, _right, _bottom, _top);
+  GuiBehavior::adjust_region();
+  _rgn->set_frame(_left, _right, _bottom, _top);
 }
 
 void GuiRollover::set_priority(GuiLabel* l, const GuiItem::Priority p) {
   _off->set_priority(l, ((p==P_Low)?GuiLabel::P_LOWER:GuiLabel::P_HIGHER));
   _on->set_priority(l, ((p==P_Low)?GuiLabel::P_LOWER:GuiLabel::P_HIGHER));
-  GuiItem::set_priority(l, p);
+  GuiBehavior::set_priority(l, p);
 }
 
 GuiRollover::GuiRollover(const string& name, GuiLabel* off, GuiLabel* on)
-  : GuiItem(name), _off(off), _on(on), _off_scale(off->get_scale()),
+  : GuiBehavior(name), _off(off), _on(on), _off_scale(off->get_scale()),
     _on_scale(on->get_scale()), _state(false) {
   GetExtents(off, on, _left, _right, _bottom, _top);
-  _rgn = new GuiRegion("rollover-" + name, _left, _right, _bottom, _top,
-		       false);
-  rollovers["gui-in-rollover-" + name] = this;
-  rollovers["gui-out-rollover-" + name] = this;
+  _rgn = new MouseWatcherRegion("rollover-" + name, _left, _right, _bottom,
+				_top);
+  _rgn->set_suppress_below(false);
+  rollovers.insert(this);
 }
 
 GuiRollover::~GuiRollover(void) {
@@ -96,37 +85,41 @@ GuiRollover::~GuiRollover(void) {
   // 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);
+  rollovers.erase(this);
+  if ((rollovers.size() == 0) && added_hooks) {
+    _eh->remove_hook("gui-enter", enter_rollover);
+    _eh->remove_hook("gui-exit", exit_rollover);
+    added_hooks = false;
+  }
 }
 
 void GuiRollover::manage(GuiManager* mgr, EventHandler& eh) {
-  if (!_added_hooks) {
-    eh.add_hook("gui-in-rollover-" + get_name(), enter_rollover);
-    eh.add_hook("gui-out-rollover-" + get_name(), exit_rollover);
-    _added_hooks = true;
+  if (!added_hooks) {
+    eh.add_hook("gui-enter", enter_rollover);
+    eh.add_hook("gui-exit", exit_rollover);
+    added_hooks = true;
   }
   if (_mgr == (GuiManager*)0L) {
     mgr->add_region(_rgn);
     _state = false;
     mgr->add_label(_off);
-    GuiItem::manage(mgr, eh);
+    GuiBehavior::manage(mgr, eh);
   } else
     gui_cat->warning() << "tried to manage rollover (0x" << (void*)this
 		       << ") that is already managed" << endl;
 }
 
 void GuiRollover::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
-  if (!_added_hooks) {
-    eh.add_hook("gui-in-rollover-" + get_name(), enter_rollover);
-    eh.add_hook("gui-out-rollover-" + get_name(), exit_rollover);
-    _added_hooks = true;
+  if (!added_hooks) {
+    eh.add_hook("gui-enter", enter_rollover);
+    eh.add_hook("gui-exit", exit_rollover);
+    added_hooks = true;
   }
   if (_mgr == (GuiManager*)0L) {
     mgr->add_region(_rgn);
     _state = false;
     mgr->add_label(_off, n);
-    GuiItem::manage(mgr, eh, n);
+    GuiBehavior::manage(mgr, eh, n);
   } else
     gui_cat->warning() << "tried to manage rollover (0x" << (void*)this
 		       << ") that is already managed" << endl;
@@ -138,7 +131,7 @@ void GuiRollover::unmanage(void) {
     _mgr->remove_label(_off);
     _mgr->remove_label(_on);
   }
-  GuiItem::unmanage();
+  GuiBehavior::unmanage();
 }
 
 int GuiRollover::freeze(void) {
@@ -156,21 +149,21 @@ int GuiRollover::thaw(void) {
 void GuiRollover::set_scale(float f) {
   _on->set_scale(f * _on_scale);
   _off->set_scale(f * _off_scale);
-  GuiItem::set_scale(f);
+  GuiBehavior::set_scale(f);
   recompute_frame();
 }
 
 void GuiRollover::set_scale(float x, float y, float z) {
   _on->set_scale(x, y, z);
   _off->set_scale(x, y, z);
-  GuiItem::set_scale(x, y, z);
+  GuiBehavior::set_scale(x, y, z);
   recompute_frame();
 }
 
 void GuiRollover::set_pos(const LVector3f& p) {
   _on->set_pos(p);
   _off->set_pos(p);
-  GuiItem::set_pos(p);
+  GuiBehavior::set_pos(p);
   recompute_frame();
 }
 
@@ -185,21 +178,34 @@ void GuiRollover::set_priority(GuiItem* i, const GuiItem::Priority p) {
     i->set_priority(_off, ((p==P_Low)?P_High:P_Low));
     i->set_priority(_on, ((p==P_Low)?P_High:P_Low));
   }
-  GuiItem::set_priority(i, p);
+  GuiBehavior::set_priority(i, p);
+}
+
+void GuiRollover::start_behavior(void) {
+  return;
+}
+
+void GuiRollover::stop_behavior(void) {
+  return;
+}
+
+void GuiRollover::reset_behavior(void) {
+  return;
 }
 
 int GuiRollover::set_draw_order(int v) {
   int o = _off->set_draw_order(v);
   o = _on->set_draw_order(o);
-  return GuiItem::set_draw_order(o);
+  _rgn->set_sort(o++);
+  return GuiBehavior::set_draw_order(o);
 }
 
 void GuiRollover::output(ostream& os) const {
-  GuiItem::output(os);
+  GuiBehavior::output(os);
   os << "  Rollover data:" << endl;
   os << "    off - 0x" << (void*)_off << endl;
   os << "    on - 0x" << (void*)_on << endl;
-  os << "    region - 0x" << (void*)_rgn << endl;
+  os << "    region - 0x" << (void*)_rgn << " (" << *_rgn << ")" << endl;
   os << "      frame - " << _rgn->get_frame() << endl;
   os << "    state - " << _state << endl;
 }

+ 13 - 5
panda/src/gui/guiRollover.h

@@ -6,16 +6,17 @@
 #ifndef __GUIROLLOVER_H__
 #define __GUIROLLOVER_H__
 
-#include "guiItem.h"
-#include "guiRegion.h"
+#include "guiBehavior.h"
 #include "guiLabel.h"
 #include "guiManager.h"
 
-class EXPCL_PANDA GuiRollover : public GuiItem {
+#include <mouseWatcherRegion.h>
+
+class EXPCL_PANDA GuiRollover : public GuiBehavior {
 private:
   PT(GuiLabel) _off;
   PT(GuiLabel) _on;
-  PT(GuiRegion) _rgn;
+  PT(MouseWatcherRegion) _rgn;
 
   float _off_scale;
   float _on_scale;
@@ -48,10 +49,17 @@ PUBLISHED:
   virtual void set_priority(GuiLabel*, const Priority);
   virtual void set_priority(GuiItem*, const Priority);
 
+  virtual void start_behavior(void);
+  virtual void stop_behavior(void);
+  virtual void reset_behavior(void);
+
   virtual int set_draw_order(int);
 
   virtual void output(ostream&) const;
 
+public:
+  INLINE bool owns_region(const MouseWatcherRegion*) const;
+
 public:
   // type interface
   static TypeHandle get_class_type(void) {
@@ -60,7 +68,7 @@ public:
   static void init_type(void) {
     GuiItem::init_type();
     register_type(_type_handle, "GuiRollover",
-		  GuiItem::get_class_type());
+		  GuiBehavior::get_class_type());
   }
   virtual TypeHandle get_type(void) const {
     return get_class_type();

+ 0 - 10
panda/src/gui/guiSign.cxx

@@ -30,8 +30,6 @@ GuiSign::~GuiSign(void) {
 }
 
 void GuiSign::manage(GuiManager* mgr, EventHandler& eh) {
-  if (!_added_hooks)
-    _added_hooks = true;
   if (_mgr == (GuiManager*)0L) {
     mgr->add_label(_sign);
     GuiItem::manage(mgr, eh);
@@ -41,8 +39,6 @@ void GuiSign::manage(GuiManager* mgr, EventHandler& eh) {
 }
 
 void GuiSign::manage(GuiManager* mgr, EventHandler& eh, Node* n) {
-  if (!_added_hooks)
-    _added_hooks = true;
   if (_mgr == (GuiManager*)0L) {
     mgr->add_label(_sign, n);
     GuiItem::manage(mgr, eh, n);
@@ -58,16 +54,10 @@ void GuiSign::unmanage(void) {
 }
 
 int GuiSign::freeze() {
-#ifdef _DEBUG
-  gui_cat->spam() << "GuiSign::freeze (" << this->get_name() << ")" << endl;
-#endif
   return _sign->freeze();
 }
 
 int GuiSign::thaw() {
-#ifdef _DEBUG
-  gui_cat->spam() << "GuiSign::thaw (" << this->get_name() << ")" << endl;
-#endif
   return _sign->thaw();
 }