// Filename: guiFrame.cxx // Created by: cary (01Nov00) // //////////////////////////////////////////////////////////////////// #include "guiFrame.h" TypeHandle GuiFrame::_type_handle; class PosFrame { private: LVector3f _pos; LVector4f _frame; public: PosFrame(GuiItem* i) : _pos(i->get_pos()), _frame(i->get_frame()) {} PosFrame(void) {} PosFrame(const PosFrame& c) : _pos(c._pos), _frame(c._frame) {} inline PosFrame& operator=(const PosFrame& c) { _pos = c._pos; _frame = c._frame; return *this; } inline void write(GuiItem* i) { i->set_pos(_pos); } inline LVector3f get_pos(void) const { return _pos; } inline LVector4f get_frame(void) const { return _frame; } inline void set_pos(LVector3f p) { LVector3f d = p - _pos; float du = d.dot(LVector3f::up()); float dr = d.dot(LVector3f::right()); _frame[0] += dr; _frame[1] += dr; _frame[2] += du; _frame[3] += du; _pos = p; } }; typedef map UtilMap; GuiFrame::Boxes::iterator GuiFrame::find_box(GuiItem* item) { bool found = false; Boxes::iterator ret = _items.end(); 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; } #include void GuiFrame::recompute_frame(void) { GuiItem::recompute_frame(); freeze(); Boxes::iterator i; UtilMap _map; // 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) { GuiItem* here = (*i).get_item(); here->recompute(); _map[here] = PosFrame(here); } for (i=_items.begin(); i!=_items.end(); ++i) { GuiItem* here = (*i).get_item(); // here->recompute(); int n = (*i).get_num_links(); if (n > 0) { UtilMap::iterator ui = _map.find(here); LVector4f ext_h = (*ui).second.get_frame(); LVector3f pos_h = (*ui).second.get_pos(); for (int j=0; jwarning() << "unknown packing type (" << (int)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) { UtilMap::iterator ui = _map.find((*i).get_item()); float tmp = ((*ui).second.get_frame())[0]; _left = (_leftadjust_region(); thaw(); } void GuiFrame::set_priority(GuiLabel* l, const GuiItem::Priority p) { Boxes::iterator i; for (i=_items.begin(); i!=_items.end(); ++i) { GuiItem* here = (*i).get_item(); here->set_priority(l, p); } } GuiFrame::GuiFrame(const string& name) : GuiItem(name), _align_to_left(false), _align_to_right(false), _align_to_top(false), _align_to_bottom(false) { } GuiFrame::~GuiFrame(void) { this->unmanage(); } int GuiFrame::freeze() { int result = 0; Boxes::iterator i; for (i=_items.begin(); i!=_items.end(); ++i) { GuiItem* here = (*i).get_item(); int count = here->freeze(); result = max(result, count); } return result; } int GuiFrame::thaw() { int result = 0; Boxes::iterator i; for (i=_items.begin(); i!=_items.end(); ++i) { GuiItem* here = (*i).get_item(); int count = here->thaw(); result = max(result, count); } return result; } void GuiFrame::add_item(GuiItem* item) { bool found = false; for (Boxes::iterator i=_items.begin(); (!found)&&(i!=_items.end()); ++i) if ((*i).get_item() == item) found = true; if (!found) { _items.push_back(Box(item)); // this->recompute_frame(); } } void GuiFrame::remove_item(GuiItem* item) { Boxes::iterator i = find_box(item); if (i == _items.end()) return; item->unmanage(); (*i).erase_all_links(); // should NEVER link forward in the items, only backward, so it should be // safe to start here, and go to the end for (Boxes::iterator j=i+1; j!=_items.end(); ++j) { bool done; do { done = true; for (int k=0; k<(*j).get_num_links(); ++k) if ((*j).get_nth_to(k) == item) { done = false; (*j).erase_nth_link(k); break; } } while (!done); } // now get rid of the thing itself _items.erase(i); this->recompute(); } void GuiFrame::pack_item(GuiItem* item, Packing rel, GuiItem* to, float gap) { 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, to, gap)); // this->recompute_frame(); } void GuiFrame::clear_packing(GuiItem* item) { Boxes::iterator box = find_box(item); (*box).erase_all_links(); // this->recompute_frame(); } void GuiFrame::clear_all_packing(void) { for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) (*i).erase_all_links(); // this->recompute_frame(); } void GuiFrame::manage(GuiManager* mgr, EventHandler& eh) { 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::manage(GuiManager* mgr, EventHandler& eh, Node* n) { if (_mgr == (GuiManager*)0L) { for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) (*i).get_item()->manage(mgr, eh, n); GuiItem::manage(mgr, eh, n); } 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 * (*i).get_scale()); GuiItem::set_scale(f); // this->recompute_frame(); } void GuiFrame::set_scale(float x, float y, float z) { for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) (*i).get_item()->set_scale(x * (*i).get_item()->get_scale_x(), y * (*i).get_item()->get_scale_y(), z * (*i).get_item()->get_scale_z()); GuiItem::set_scale(x, y, z); } 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(); } void GuiFrame::set_priority(GuiItem* it, const GuiItem::Priority p) { Boxes::iterator i; for (i=_items.begin(); i!=_items.end(); ++i) { GuiItem* here = (*i).get_item(); here->set_priority(it, p); } } int GuiFrame::set_draw_order(int v) { int o = v; bool first = true; for (Boxes::iterator i=_items.begin(); i!=_items.end(); ++i) if (first) { first = false; o = (*i).get_item()->set_draw_order(v); } else o = (*i).get_item()->set_draw_order(o); return GuiItem::set_draw_order(o); } void GuiFrame::output(ostream& os) const { GuiItem::output(os); os << " Frame data:" << endl; Boxes::const_iterator i; for (i=_items.begin(); i!=_items.end(); ++i) { os << " box - 0x" << (void*)((*i).get_item()) << endl; int n = (*i).get_num_links(); if (n > 0) { for (int j=0; j