diff --git a/panda/src/gui/Sources.pp b/panda/src/gui/Sources.pp index 0341c12327..69414e43b8 100644 --- a/panda/src/gui/Sources.pp +++ b/panda/src/gui/Sources.pp @@ -11,21 +11,27 @@ 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 \ - guiButton.h guiButton.I guiButton.cxx + guiButton.h guiButton.I guiButton.cxx \ + guiFrame.h guiFrame.I guiFrame.cxx #define INSTALL_HEADERS \ guiManager.h guiManager.I \ guiRegion.h guiRegion.I \ guiLabel.h guiLabel.I \ + guiItem.h guiItem.I \ guiRollover.h guiRollover.I \ - guiButton.h guiButton.I + guiButton.h guiButton.I \ + guiFrame.h guiFrame.I #define IGATESCAN \ guiManager.h guiManager.I \ guiRegion.h guiRegion.I \ guiLabel.h guiLabel.I \ + guiItem.h guiItem.I \ guiRollover.h guiRollover.I \ - guiButton.h guiButton.I + guiButton.h guiButton.I \ + guiFrame.h guiFrame.I #end lib_target diff --git a/panda/src/gui/guiButton.I b/panda/src/gui/guiButton.I index cc34f321f7..a4ffc0a0e8 100644 --- a/panda/src/gui/guiButton.I +++ b/panda/src/gui/guiButton.I @@ -157,37 +157,3 @@ INLINE const string& GuiButton::get_down_rollover_event(void) const { INLINE const string& GuiButton::get_inactive_event(void) const { return _inactive_event; } - -INLINE void GuiButton::set_scale(float f) { - _up->set_scale(f); - _down->set_scale(f); - if (_up_rollover != (GuiLabel*)0L) - _up_rollover->set_scale(f); - if (_down_rollover != (GuiLabel*)0L) - _down_rollover->set_scale(f); - if (_inactive != (GuiLabel*)0L) - _inactive->set_scale(f); - _scale = f; - recompute_frame(); -} - -INLINE 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); - _pos = p; - recompute_frame(); -} - -INLINE float GuiButton::get_scale(void) const { - return _scale; -} - -INLINE LVector3f GuiButton::get_pos(void) const { - return _pos; -} diff --git a/panda/src/gui/guiButton.cxx b/panda/src/gui/guiButton.cxx index 20271d1cbf..b6790767c5 100644 --- a/panda/src/gui/guiButton.cxx +++ b/panda/src/gui/guiButton.cxx @@ -156,25 +156,22 @@ void GuiButton::switch_state(GuiButton::States nstate) { } void GuiButton::recompute_frame(void) { - float left, right, bottom, top; - - GetExtents(_up, _down, _up_rollover, _down_rollover, _inactive, left, right, - bottom, top); - _rgn->set_region(left, right, bottom, top); + GuiItem::recompute_frame(); + GetExtents(_up, _down, _up_rollover, _down_rollover, _inactive, _left, + _right, _bottom, _top); + _rgn->set_region(_left, _right, _bottom, _top); } GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* up_roll, GuiLabel* down, GuiLabel* down_roll, GuiLabel* inactive) - : Namable(name), _up(up), _up_rollover(up_roll), _down(down), + : GuiItem(name), _up(up), _up_rollover(up_roll), _down(down), _down_rollover(down_roll), _inactive(inactive), _state(GuiButton::NONE), - _added_hooks(false), _mgr((GuiManager*)0L), _up_event(name + "-up"), - _up_rollover_event(name + "-up-rollover"), _down_event(name +"-down"), - _down_rollover_event(name + "-down-rollover"), + _up_event(name + "-up"), _up_rollover_event(name + "-up-rollover"), + _down_event(name +"-down"), _down_rollover_event(name + "-down-rollover"), _inactive_event(name + "-inactive") { - float left, right, bottom, top; - - GetExtents(up, down, up_roll, down_roll, inactive, left, right, bottom, top); - _rgn = new GuiRegion("button-" + name, left, right, bottom, top, true); + 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; @@ -196,7 +193,7 @@ void GuiButton::manage(GuiManager* mgr, EventHandler& eh) { } if (_mgr == (GuiManager*)0L) { mgr->add_region(_rgn); - _mgr = mgr; + GuiItem::manage(mgr, eh); switch_state(UP); } else gui_cat->warning() << "tried to manage button (0x" << (void*)this @@ -206,5 +203,31 @@ void GuiButton::manage(GuiManager* mgr, EventHandler& eh) { void GuiButton::unmanage(void) { _mgr->remove_region(_rgn); switch_state(NONE); - _mgr = (GuiManager*)0L; + GuiItem::unmanage(); +} + +void GuiButton::set_scale(float f) { + _up->set_scale(f); + _down->set_scale(f); + if (_up_rollover != (GuiLabel*)0L) + _up_rollover->set_scale(f); + if (_down_rollover != (GuiLabel*)0L) + _down_rollover->set_scale(f); + if (_inactive != (GuiLabel*)0L) + _inactive->set_scale(f); + GuiItem::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); + GuiItem::set_pos(p); + this->recompute_frame(); } diff --git a/panda/src/gui/guiButton.h b/panda/src/gui/guiButton.h index 21d4cebdcb..624897d562 100644 --- a/panda/src/gui/guiButton.h +++ b/panda/src/gui/guiButton.h @@ -6,13 +6,12 @@ #ifndef __GUIBUTTON_H__ #define __GUIBUTTON_H__ +#include "guiItem.h" #include "guiRegion.h" #include "guiLabel.h" #include "guiManager.h" -#include - -class EXPCL_PANDA GuiButton : public Namable { +class EXPCL_PANDA GuiButton : public GuiItem { private: GuiLabel* _up; GuiLabel* _up_rollover; @@ -26,21 +25,17 @@ private: enum States { NONE, UP, UP_ROLLOVER, DOWN, DOWN_ROLLOVER, INACTIVE, INACTIVE_ROLLOVER }; States _state; - bool _added_hooks; - float _scale; - LVector3f _pos; - GuiManager* _mgr; INLINE GuiButton(void); void switch_state(States); - void recompute_frame(void); + virtual void recompute_frame(void); public: GuiButton(const string&, GuiLabel*, GuiLabel*, GuiLabel*, GuiLabel*, GuiLabel*); ~GuiButton(void); - void manage(GuiManager*, EventHandler&); - void unmanage(void); + virtual void manage(GuiManager*, EventHandler&); + virtual void unmanage(void); INLINE void enter(void); INLINE void exit(void); INLINE void up(void); @@ -64,11 +59,8 @@ public: INLINE const string& get_down_rollover_event(void) const; INLINE const string& get_inactive_event(void) const; - INLINE void set_scale(float); - INLINE void set_pos(const LVector3f&); - - INLINE float get_scale(void) const; - INLINE LVector3f get_pos(void) const; + virtual void set_scale(float); + virtual void set_pos(const LVector3f&); }; #include "guiButton.I" diff --git a/panda/src/gui/guiFrame.I b/panda/src/gui/guiFrame.I index 8324d31bfc..8ad4e5983c 100644 --- a/panda/src/gui/guiFrame.I +++ b/panda/src/gui/guiFrame.I @@ -2,3 +2,5 @@ // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// + +INLINE GuiFrame::GuiFrame(void) {} diff --git a/panda/src/gui/guiFrame.cxx b/panda/src/gui/guiFrame.cxx index 2015498de5..507a0b788b 100644 --- a/panda/src/gui/guiFrame.cxx +++ b/panda/src/gui/guiFrame.cxx @@ -2,3 +2,188 @@ // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// + +#include "guiFrame.h" + +GuiFrame::Boxes::iterator GuiFrame::find_box(GuiItem* item) { + bool found = false; + Boxes::iterator ret; + Boxes::iterator i; + for (i=_items.begin(); (!found)&&(i!=_items.end()); ++i) + if ((*i).get_item() == item) { + found = true; + ret = i; + } + if (!found) + ret = _items.end(); + return ret; +} + +void GuiFrame::recompute_frame(void) { + GuiItem::recompute_frame(); + Boxes::iterator i; + // go thru and make sure everything is packed correctly. This is a stupid + // and brute-force algorithm. Hopefully it will be replaced with something + // more ellegant later + for (i=_items.begin(); i!=_items.end(); ++i) { + int n = (*i).get_num_links(); + if (n > 0) { + GuiItem* here = (*i).get_item(); + LVector4f ext_h = here->get_frame(); + float x_h = (ext_h[0] + ext_h[1]) / 2.; + float y_h = (ext_h[2] + ext_h[3]) / 2.; + for (int j=0; jget_frame(); + float x_t = (ext_t[0] + ext_h[1]) / 2.; + float y_t = (ext_t[2] + ext_h[3]) / 2.; + switch (pack) { + case ABOVE: + { + // to(top) - here(bottom) + float diff = ext_t[3] - ext_h[2]; + y_h += diff; + here->set_pos(LVector3f::rfu(x_h, 0., y_h)); + ext_h = here->get_frame(); + } + break; + case UNDER: + { + // to(bottom) - here(top) + float diff = ext_t[2] - ext_h[3]; + y_h += diff; + here->set_pos(LVector3f::rfu(x_h, 0., y_h)); + ext_h = here->get_frame(); + } + break; + case LEFT: + { + // to(left) - here(right) + float diff = ext_t[0] - ext_h[1]; + x_h += diff; + here->set_pos(LVector3f::rfu(x_h, 0., y_h)); + ext_h = here->get_frame(); + } + break; + case RIGHT: + { + // to(right) - here(left) + float diff = ext_t[1] - ext_h[0]; + x_h += diff; + here->set_pos(LVector3f::rfu(x_h, 0., y_h)); + ext_h = here->get_frame(); + } + break; + default: + gui_cat->warning() << "unknown packing type (" << pack << ")" + << endl; + } + } + } + } + // these should be exactly opposite the max, so they will (hopefully) be + // overwritten + _left = _bottom = 10000000.; + _right = _top = -10000000.; + for (i=_items.begin(); i!=_items.end(); ++i) { + float tmp = (*i).get_item()->get_left(); + _left = (_leftget_right(); + _right = (_rightget_bottom(); + _bottom = (_bottomget_top(); + _top = (_topset_pos(foo->get_pos() + delta); + } + // lastly, get the finial bounds + _left = _bottom = 10000000.; + _right = _top = -10000000.; + for (i=_items.begin(); i!=_items.end(); ++i) { + float tmp = (*i).get_item()->get_left(); + _left = (_leftget_right(); + _right = (_rightget_bottom(); + _bottom = (_bottomget_top(); + _top = (_toprecompute_frame(); + } +} + +void GuiFrame::pack_item(GuiItem* item, Packing rel, GuiItem* to) { + Boxes::iterator box = find_box(item); + if (box == _items.end()) { + gui_cat->warning() << "tried to pack an item we don't have yet" << endl; + return; + } + Boxes::iterator tobox = find_box(to); + if (tobox == _items.end()) { + gui_cat->warning() + << "tried to pack an item relative to something we don't have" << endl; + return; + } + (*box).add_link(Connection(rel, (*tobox).get_item())); + this->recompute_frame(); +} + +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); + GuiItem::manage(mgr, eh); + } else + gui_cat->warning() << "tried to manage frame (0x" << (void*)this + << ") that is already managed" << endl; +} + +void GuiFrame::unmanage(void) { + for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) + (*i).get_item()->unmanage(); + GuiItem::unmanage(); +} + +void GuiFrame::set_scale(float f) { + for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) + (*i).get_item()->set_scale(f); + GuiItem::set_scale(f); + this->recompute_frame(); +} + +void GuiFrame::set_pos(const LVector3f& p) { + for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) + (*i).get_item()->set_pos(p); + GuiItem::set_pos(p); + this->recompute_frame(); +} diff --git a/panda/src/gui/guiFrame.h b/panda/src/gui/guiFrame.h index 8b34749b84..83b96e5fa4 100644 --- a/panda/src/gui/guiFrame.h +++ b/panda/src/gui/guiFrame.h @@ -2,3 +2,74 @@ // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// + +#ifndef __GUIFRAME_H__ +#define __GUIFRAME_H__ + +#include "guiItem.h" + +#include + +class EXPCL_PANDA GuiFrame : public GuiItem { +public: + enum Packing { NONE, ABOVE, UNDER, LEFT, RIGHT }; +private: + class Connection { + private: + Packing _how; + GuiItem* _who; + public: + inline Connection(void) : _how(NONE), _who((GuiItem*)0L) {} + inline Connection(Packing how, GuiItem* who) : _how(how), _who(who) {} + inline Connection(const Connection& c) : _how(c._how), _who(c._who) {} + ~Connection(void) {} + + inline void set_how(Packing how) { _how = how; } + inline void set_who(GuiItem* who) { _who = who; } + + inline Packing get_how(void) const { return _how; } + inline GuiItem* get_who(void) const { return _who; } + }; + typedef vector Connections; + class Box { + private: + GuiItem* _thing; + Connections _links; + public: + inline Box(void) : _thing((GuiItem*)0L) {} + inline Box(GuiItem* i) : _thing(i) {} + inline Box(const Box& c) : _thing(c._thing), _links(c._links) {} + ~Box(void) {} + + inline void set_item(GuiItem* i) { _thing = i; } + inline void add_link(Connection c) { _links.push_back(c); } + + inline GuiItem* get_item(void) const { return _thing; } + inline int get_num_links(void) const { return _links.size(); } + inline Packing get_nth_packing(int n) const { return _links[n].get_how(); } + inline GuiItem* get_nth_to(int n) const { return _links[n].get_who(); } + }; + typedef vector Boxes; + + Boxes _items; + + INLINE GuiFrame(void); + Boxes::iterator find_box(GuiItem*); + virtual void recompute_frame(void); +public: + GuiFrame(const string&); + ~GuiFrame(void); + + void add_item(GuiItem*); + void pack_item(GuiItem*, Packing, GuiItem*); + + virtual void manage(GuiManager*, EventHandler&); + virtual void unmanage(void); + + virtual void set_scale(float); + virtual void set_pos(const LVector3f&); +}; + +#include "guiFrame.I" + +#endif /* __GUIFRAME_H__ */ diff --git a/panda/src/gui/guiItem.I b/panda/src/gui/guiItem.I index 40d650d9e0..36db87f07b 100644 --- a/panda/src/gui/guiItem.I +++ b/panda/src/gui/guiItem.I @@ -2,3 +2,34 @@ // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// + +INLINE GuiItem::GuiItem(void) : Namable("fubar"), _left(-1.), _right(1.), + _bottom(-1.), _top(1.) {} + +INLINE float GuiItem::get_scale(void) const { + return _scale; +} + +INLINE LVector3f GuiItem::get_pos(void) const { + return _pos; +} + +INLINE float GuiItem::get_left(void) const { + return _left; +} + +INLINE float GuiItem::get_right(void) const { + return _right; +} + +INLINE float GuiItem::get_bottom(void) const { + return _bottom; +} + +INLINE float GuiItem::get_top(void) const { + return _top; +} + +INLINE LVector4f GuiItem::get_frame(void) const { + return LVector4f(_left, _right, _bottom, _top); +} diff --git a/panda/src/gui/guiItem.cxx b/panda/src/gui/guiItem.cxx index 4f29a82fc4..fd3155582b 100644 --- a/panda/src/gui/guiItem.cxx +++ b/panda/src/gui/guiItem.cxx @@ -2,3 +2,31 @@ // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// + +#include "guiItem.h" + +void GuiItem::recompute_frame(void) { +} + +GuiItem::GuiItem(const string& name) : Namable(name), _added_hooks(false), + _mgr((GuiManager*)0L) { +} + +GuiItem::~GuiItem(void) { +} + +void GuiItem::manage(GuiManager* mgr, EventHandler&) { + _mgr = mgr; +} + +void GuiItem::unmanage(void) { + _mgr = (GuiManager*)0L; +} + +void GuiItem::set_scale(float f) { + _scale = f; +} + +void GuiItem::set_pos(const LVector3f& p) { + _pos = p; +} diff --git a/panda/src/gui/guiItem.h b/panda/src/gui/guiItem.h index 905cb5d37c..e419641901 100644 --- a/panda/src/gui/guiItem.h +++ b/panda/src/gui/guiItem.h @@ -2,3 +2,42 @@ // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// + +#ifndef __GUIITEM_H__ +#define __GUIITEM_H__ + +#include "guiManager.h" + +#include + +class EXPCL_PANDA GuiItem : public Namable { +protected: + bool _added_hooks; + float _scale, _left, _right, _bottom, _top; + LVector3f _pos; + GuiManager* _mgr; + + INLINE GuiItem(void); + virtual void recompute_frame(void) = 0; +public: + GuiItem(const string&); + ~GuiItem(void); + + virtual void manage(GuiManager*, EventHandler&) = 0; + virtual void unmanage(void) = 0; + + virtual void set_scale(float) = 0; + virtual void set_pos(const LVector3f&) = 0; + + INLINE float get_scale(void) const; + INLINE LVector3f get_pos(void) const; + INLINE float get_left(void) const; + INLINE float get_right(void) const; + INLINE float get_bottom(void) const; + INLINE float get_top(void) const; + INLINE LVector4f get_frame(void) const; +}; + +#include "guiItem.I" + +#endif /* __GUIITEM_H__ */ diff --git a/panda/src/gui/guiRollover.I b/panda/src/gui/guiRollover.I index b1f4f20a11..d4b9885e8e 100644 --- a/panda/src/gui/guiRollover.I +++ b/panda/src/gui/guiRollover.I @@ -33,25 +33,3 @@ INLINE void GuiRollover::exit(void) { INLINE bool GuiRollover::is_over(void) const { return _state; } - -INLINE void GuiRollover::set_scale(float f) { - _on->set_scale(f); - _off->set_scale(f); - recompute_frame(); - _scale = f; -} - -INLINE void GuiRollover::set_pos(const LVector3f& p) { - _on->set_pos(p); - _off->set_pos(p); - recompute_frame(); - _pos = p; -} - -INLINE float GuiRollover::get_scale(void) const { - return _scale; -} - -INLINE LVector3f GuiRollover::get_pos(void) const { - return _pos; -} diff --git a/panda/src/gui/guiRollover.cxx b/panda/src/gui/guiRollover.cxx index f22a9b3429..25a30e392c 100644 --- a/panda/src/gui/guiRollover.cxx +++ b/panda/src/gui/guiRollover.cxx @@ -33,21 +33,18 @@ static void exit_rollover(CPT_Event e) { } void GuiRollover::recompute_frame(void) { - float left, right, bottom, top; - - GetExtents(_off, _on, left, right, bottom, top); - _rgn->set_region(left, right, bottom, top); + GuiItem::recompute_frame(); + GetExtents(_off, _on, _left, _right, _bottom, _top); + _rgn->set_region(_left, _right, _bottom, _top); } GuiRollover::GuiRollover(const string& name, GuiLabel* off, GuiLabel* on) - : Namable(name), _off(off), _on(on), _state(false), _added_hooks(false) { - float left, right, bottom, top; - - GetExtents(off, on, left, right, bottom, top); - _rgn = new GuiRegion("rollover-" + name, left, right, bottom, top, false); + : GuiItem(name), _off(off), _on(on), _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; - _mgr = (GuiManager*)0L; } GuiRollover::~GuiRollover(void) { @@ -63,7 +60,7 @@ void GuiRollover::manage(GuiManager* mgr, EventHandler& eh) { mgr->add_region(_rgn); _state = false; mgr->add_label(_off); - _mgr = mgr; + GuiItem::manage(mgr, eh); } else gui_cat->warning() << "tried to manage rollover (0x" << (void*)this << ") that is already managed" << endl; @@ -73,5 +70,19 @@ void GuiRollover::unmanage(void) { _mgr->remove_region(_rgn); _mgr->remove_label(_off); _mgr->remove_label(_on); - _mgr = (GuiManager*)0L; + GuiItem::unmanage(); +} + +void GuiRollover::set_scale(float f) { + _on->set_scale(f); + _off->set_scale(f); + GuiItem::set_scale(f); + recompute_frame(); +} + +void GuiRollover::set_pos(const LVector3f& p) { + _on->set_pos(p); + _off->set_pos(p); + GuiItem::set_pos(p); + recompute_frame(); } diff --git a/panda/src/gui/guiRollover.h b/panda/src/gui/guiRollover.h index ee3996e174..e8e7cb9381 100644 --- a/panda/src/gui/guiRollover.h +++ b/panda/src/gui/guiRollover.h @@ -6,43 +6,34 @@ #ifndef __GUIROLLOVER_H__ #define __GUIROLLOVER_H__ +#include "guiItem.h" #include "guiRegion.h" #include "guiLabel.h" #include "guiManager.h" -#include - -class EXPCL_PANDA GuiRollover : public Namable { +class EXPCL_PANDA GuiRollover : public GuiItem { private: GuiLabel* _off; GuiLabel* _on; GuiRegion* _rgn; bool _state; - bool _added_hooks; - GuiManager* _mgr; - - float _scale; - LVector3f _pos; INLINE GuiRollover(void); - void recompute_frame(void); + virtual void recompute_frame(void); public: GuiRollover(const string&, GuiLabel*, GuiLabel*); ~GuiRollover(void); - void manage(GuiManager*, EventHandler&); - void unmanage(void); + virtual void manage(GuiManager*, EventHandler&); + virtual void unmanage(void); INLINE void enter(void); INLINE void exit(void); INLINE bool is_over(void) const; - INLINE void set_scale(float); - INLINE void set_pos(const LVector3f&); - - INLINE float get_scale(void) const; - INLINE LVector3f get_pos(void) const; + virtual void set_scale(float); + virtual void set_pos(const LVector3f&); }; #include "guiRollover.I"