| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- // Filename: guiButton.cxx
- // Created by: cary (30Oct00)
- //
- ////////////////////////////////////////////////////////////////////
- #include "guiButton.h"
- #include "config_gui.h"
- #include <throw_event.h>
- #include <map>
- typedef map<string, GuiButton*> ButtonMap;
- 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;
- v->get_extents(l1, r1, b1, t1);
- w->get_extents(l2, r2, b2, t2);
- l1 = (l1<l2)?l1:l2;
- r1 = (r1<r2)?r2:r1;
- b1 = (b1<b2)?b1:b2;
- t1 = (t1<t2)?t2:t1;
- if (x != (GuiLabel*)0L) {
- x->get_extents(l2, r2, b2, t2);
- l1 = (l1<l2)?l1:l2;
- r1 = (r1<r2)?r2:r1;
- b1 = (b1<b2)?b1:b2;
- t1 = (t1<t2)?t2:t1;
- }
- if (y != (GuiLabel*)0L) {
- y->get_extents(l2, r2, b2, t2);
- l1 = (l1<l2)?l1:l2;
- r1 = (r1<r2)?r2:r1;
- b1 = (b1<b2)?b1:b2;
- t1 = (t1<t2)?t2:t1;
- }
- if (z != (GuiLabel*)0L) {
- z->get_extents(l2, r2, b2, t2);
- l = (l1<l2)?l1:l2;
- r = (r1<r2)?r2:r1;
- b = (b1<b2)?b1:b2;
- t = (t1<t2)?t2:t1;
- }
- }
- static void enter_button(CPT_Event e) {
- 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 = 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_down(CPT_Event e) {
- 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->down();
- }
- static void click_button_up(CPT_Event e) {
- 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->up();
- }
- void GuiButton::switch_state(GuiButton::States nstate) {
- test_ref_count_integrity();
- // cleanup old state
- switch (_state) {
- case NONE:
- break;
- case UP:
- _mgr->remove_label(_up);
- break;
- case UP_ROLLOVER:
- _mgr->remove_label(_up_rollover);
- break;
- case DOWN:
- _mgr->remove_label(_down);
- break;
- case DOWN_ROLLOVER:
- _mgr->remove_label(_down_rollover);
- break;
- case INACTIVE:
- if (_inactive != (GuiLabel*)0L)
- _mgr->remove_label(_inactive);
- break;
- case INACTIVE_ROLLOVER:
- if (_inactive != (GuiLabel*)0L)
- _mgr->remove_label(_inactive);
- break;
- default:
- gui_cat->warning() << "switching away from invalid state (" << (int)_state
- << ")" << endl;
- }
- _state = nstate;
- // deal with new state
- switch (_state) {
- case NONE:
- _rgn->trap_clicks(false);
- break;
- case UP:
- _mgr->add_label(_up);
- if (!_up_event.empty())
- throw_event(_up_event);
- _rgn->trap_clicks(true);
- break;
- case UP_ROLLOVER:
- if (_up_rollover != (GuiLabel*)0L) {
- _mgr->add_label(_up_rollover);
- if (!_up_rollover_event.empty())
- throw_event(_up_rollover_event);
- } else {
- _mgr->add_label(_up);
- if (!_up_event.empty())
- throw_event(_up_event);
- _state = UP;
- }
- _rgn->trap_clicks(true);
- break;
- case DOWN:
- _mgr->add_label(_down);
- if (!_down_event.empty())
- throw_event(_down_event);
- _rgn->trap_clicks(true);
- break;
- case DOWN_ROLLOVER:
- if (_down_rollover != (GuiLabel*)0L) {
- _mgr->add_label(_down_rollover);
- if (!_down_rollover_event.empty())
- throw_event(_down_rollover_event);
- } else {
- _mgr->add_label(_down);
- if (!_down_event.empty())
- throw_event(_down_event);
- _state = DOWN;
- }
- _rgn->trap_clicks(true);
- break;
- case INACTIVE:
- if (_inactive != (GuiLabel*)0L) {
- _mgr->add_label(_inactive);
- if (!_inactive_event.empty())
- throw_event(_inactive_event);
- }
- _rgn->trap_clicks(false);
- break;
- case INACTIVE_ROLLOVER:
- if (_inactive != (GuiLabel*)0L) {
- _mgr->add_label(_inactive);
- if (!_inactive_event.empty())
- throw_event(_inactive_event);
- }
- _rgn->trap_clicks(false);
- break;
- default:
- gui_cat->warning() << "switched to invalid state (" << (int)_state << ")"
- << endl;
- }
- }
- void GuiButton::recompute_frame(void) {
- GuiBehavior::recompute_frame();
- _up->recompute();
- _down->recompute();
- if (_up_rollover != (GuiLabel*)0L)
- _up_rollover->recompute();
- if (_down_rollover != (GuiLabel*)0L)
- _down_rollover->recompute();
- if (_inactive != (GuiLabel*)0L)
- _inactive->recompute();
- GetExtents(_up, _down, _up_rollover, _down_rollover, _inactive, _left,
- _right, _bottom, _top);
- _rgn->set_region(_left, _right, _bottom, _top);
- }
- void GuiButton::behavior_up(CPT_Event, void* data) {
- GuiButton* button = (GuiButton*)data;
- button->run_button_up();
- }
- void GuiButton::behavior_down(CPT_Event, void* data) {
- GuiButton* button = (GuiButton*)data;
- button->run_button_down();
- }
- void GuiButton::run_button_up(void) {
- if (_eh == (EventHandler*)0L)
- return;
- _eh->remove_hook(_up_event, GuiButton::behavior_up, (void*)this);
- _eh->remove_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
- if (!_behavior_event.empty())
- throw_event(_behavior_event);
- if (_behavior_functor != (GuiBehavior::BehaviorFunctor*)0L)
- _behavior_functor->doit(this);
- }
- void GuiButton::run_button_down(void) {
- if (_eh == (EventHandler*)0L)
- return;
- _eh->add_hook(_up_event, GuiButton::behavior_up, (void*)this);
- _eh->add_hook(_up_rollover_event, GuiButton::behavior_up, (void*)this);
- }
- 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(""),
- _inactive_event(""), _up_scale(up->get_scale()), _upr_scale(1.),
- _down_scale(down->get_scale()), _downr_scale(1.), _inactive_scale(1.),
- _state(GuiButton::NONE),
- _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;
- }
- 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()),
- _upr_scale(1.), _down_scale(down->get_scale()), _downr_scale(1.),
- _inactive_scale(inactive->get_scale()), _state(GuiButton::NONE),
- _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;
- }
- 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()),
- _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),
- _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;
- }
- 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");
- buttons.erase("gui-button-" + name + "-mouse1-up");
- buttons.erase("gui-button-" + name + "-mouse2-up");
- buttons.erase("gui-button-" + name + "-mouse3-up");
- 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 (_mgr == (GuiManager*)0L) {
- mgr->add_region(_rgn);
- GuiBehavior::manage(mgr, eh);
- if (_behavior_running)
- this->start_behavior();
- switch_state(UP);
- } else
- gui_cat->warning() << "tried to manage button (0x" << (void*)this
- << ") that is already managed" << endl;
- }
- void GuiButton::unmanage(void) {
- if (_mgr != (GuiManager*)0L)
- _mgr->remove_region(_rgn);
- if (_behavior_running)
- this->stop_behavior();
- switch_state(NONE);
- GuiBehavior::unmanage();
- }
- int GuiButton::freeze() {
- _up->freeze();
- _down->freeze();
- if (_up_rollover != (GuiLabel*)0L)
- _up_rollover->freeze();
- if (_down_rollover != (GuiLabel*)0L)
- _down_rollover->freeze();
- if (_inactive != (GuiLabel*)0L)
- _inactive->freeze();
- return 0;
- }
- int GuiButton::thaw() {
- _up->thaw();
- _down->thaw();
- if (_up_rollover != (GuiLabel*)0L)
- _up_rollover->thaw();
- if (_down_rollover != (GuiLabel*)0L)
- _down_rollover->thaw();
- if (_inactive != (GuiLabel*)0L)
- _inactive->thaw();
- return 0;
- }
- void GuiButton::set_scale(float f) {
- _up->set_scale(f * _up_scale);
- _down->set_scale(f * _down_scale);
- if (_up_rollover != (GuiLabel*)0L)
- _up_rollover->set_scale(f * _upr_scale);
- if (_down_rollover != (GuiLabel*)0L)
- _down_rollover->set_scale(f * _downr_scale);
- if (_inactive != (GuiLabel*)0L)
- _inactive->set_scale(f * _inactive_scale);
- GuiBehavior::set_scale(f);
- this->recompute_frame();
- }
- void GuiButton::set_pos(const LVector3f& p) {
- _up->set_pos(p);
- _down->set_pos(p);
- if (_up_rollover != (GuiLabel*)0L)
- _up_rollover->set_pos(p);
- if (_down_rollover != (GuiLabel*)0L)
- _down_rollover->set_pos(p);
- if (_inactive != (GuiLabel*)0L)
- _inactive->set_pos(p);
- GuiBehavior::set_pos(p);
- this->recompute_frame();
- }
- void GuiButton::start_behavior(void) {
- GuiBehavior::start_behavior();
- if (_mgr == (GuiManager*)0L)
- return;
- _eh->add_hook(_down_event, GuiButton::behavior_down, (void*)this);
- _eh->add_hook(_down_rollover_event, GuiButton::behavior_down, (void*)this);
- }
- 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);
- }
- void GuiButton::reset_behavior(void) {
- GuiBehavior::reset_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);
- }
- void GuiButton::output(ostream& os) const {
- GuiBehavior::output(os);
- os << " Button data:" << endl;
- os << " up - 0x" << (void*)_up << endl;
- os << " up_rollover - 0x" << (void*)_up_rollover << endl;
- os << " down - 0x" << (void*)_down << endl;
- os << " down_rollover - 0x" << (void*)_down_rollover << endl;
- os << " inactive - 0x" << (void*)_inactive << endl;
- os << " up event - '" << _up_event << "'" << endl;
- os << " up_rollover event - '" << _up_rollover_event << "'" << endl;
- 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 << " frame - " << _rgn->get_frame() << endl;
- os << " state - " << (int)_state << endl;
- }
|