00001 #include "gui_uiobject.hpp"
00002
00003 #include "gui_frame.hpp"
00004 #include "gui_layeredregion.hpp"
00005 #include "gui_manager.hpp"
00006 #include "gui_out.hpp"
00007
00008 #include <utils_string.hpp>
00009 #include <sstream>
00010
00011 namespace gui
00012 {
00013 uiobject::uiobject(manager* pManager) :
00014 pManager_(pManager), uiID_(uint(-1)), pParent_(nullptr), pInheritance_(nullptr),
00015 bSpecial_(false), bManuallyRendered_(false), bNewlyCreated_(false),
00016 pRenderer_(nullptr), bInherits_(false), bVirtual_(false), bLoaded_(false),
00017 bReady_(true), lDefinedBorderList_({{false, false, false, false}}),
00018 lBorderList_{{0, 0, 0, 0}}, fAlpha_(1.0f), bIsShown_(true), bIsVisible_(true),
00019 bIsWidthAbs_(true), bIsHeightAbs_(true), uiAbsWidth_(0u), uiAbsHeight_(0u),
00020 fRelWidth_ (0.0f), fRelHeight_(0.0f), bUpdateAnchors_(false),
00021 bUpdateBorders_(true), bUpdateDimensions_(false)
00022 {
00023 lType_.push_back("UIObject");
00024 }
00025
00026 uiobject::~uiobject()
00027 {
00028 std::vector<lua_glue*>::iterator iter;
00029 foreach (iter, lGlueList_)
00030 (*iter)->notify_deleted();
00031 }
00032
00033 const manager* uiobject::get_manager() const
00034 {
00035 return pManager_;
00036 }
00037
00038 manager* uiobject::get_manager()
00039 {
00040 return pManager_;
00041 }
00042
00043 std::string uiobject::serialize(const std::string& sTab) const
00044 {
00045 std::ostringstream sStr;
00046
00047 sStr << sTab << " # Name : " << sName_ << " ("+std::string(bReady_ ? "ready" : "not ready")+std::string(bSpecial_ ? ", special)\n" : ")\n");
00048 sStr << sTab << " # Raw name : " << sRawName_ << "\n";
00049 sStr << sTab << " # Lua name : " << sLuaName_ << "\n";
00050 sStr << sTab << " # ID : " << uiID_ << "\n";
00051 sStr << sTab << " # Type : " << lType_.back() << "\n";
00052 if (bManuallyRendered_)
00053 sStr << sTab << " # Man. render : " << (pRenderer_ ? pRenderer_->get_name() : "none") << "\n";
00054 if (pParent_)
00055 sStr << sTab << " # Parent : " << pParent_->get_name() << "\n";
00056 else
00057 sStr << sTab << " # Parent : none\n";
00058 sStr << sTab << " # Num anchors : " << lAnchorList_.size() << "\n";
00059 if (!lAnchorList_.empty())
00060 {
00061 sStr << sTab << " |-###\n";
00062 std::map<anchor_point, anchor>::const_iterator iterAnchor;
00063 foreach (iterAnchor, lAnchorList_)
00064 {
00065 sStr << iterAnchor->second.serialize(sTab);
00066 sStr << sTab << " |-###\n";
00067 }
00068 }
00069 sStr << sTab << " # Borders :\n";
00070 sStr << sTab << " |-###\n";
00071 sStr << sTab << " | # left : " << lBorderList_[BORDER_LEFT] << "\n";
00072 sStr << sTab << " | # top : " << lBorderList_[BORDER_TOP] << "\n";
00073 sStr << sTab << " | # right : " << lBorderList_[BORDER_RIGHT] << "\n";
00074 sStr << sTab << " | # bottom : " << lBorderList_[BORDER_BOTTOM] << "\n";
00075 sStr << sTab << " |-###\n";
00076 sStr << sTab << " # Alpha : " << fAlpha_ << "\n";
00077 sStr << sTab << " # Shown : " << bIsShown_ << "\n";
00078 sStr << sTab << " # Abs width : " << uiAbsWidth_ << "\n";
00079 sStr << sTab << " # Abs height : " << uiAbsHeight_ << "\n";
00080 sStr << sTab << " # Rel width : " << fRelWidth_ << "\n";
00081 sStr << sTab << " # Rel height : " << fRelHeight_ << "\n";
00082
00083 return sStr.str();
00084 }
00085
00086 void uiobject::copy_from(uiobject* pObj)
00087 {
00088 if (pObj)
00089 {
00090
00091 if (!pObj->lCopyList_.empty())
00092 {
00093 if (is_virtual())
00094 {
00095
00096
00097 for (auto iter : pObj->lCopyList_)
00098 lCopyList_.push_back(iter);
00099 }
00100
00101 utils::wptr<lua::state> pLua = pManager_->get_lua();
00102 pLua->get_global(pObj->get_lua_name());
00103 if (pLua->get_type() != lua::TYPE_NIL)
00104 {
00105 pLua->get_global(sLuaName_);
00106 if (pLua->get_type() != lua::TYPE_NIL)
00107 {
00108 std::vector<std::string>::iterator iterVariable;
00109 foreach (iterVariable, pObj->lCopyList_)
00110 {
00111 pLua->get_field(*iterVariable, -2);
00112 pLua->set_field(*iterVariable);
00113 }
00114 }
00115 pLua->pop();
00116 }
00117 pLua->pop();
00118 }
00119
00120 bInherits_ = true;
00121 pInheritance_ = pObj;
00122
00123
00124 this->set_alpha(pObj->get_alpha());
00125 this->set_shown(pObj->is_shown());
00126 if (pObj->is_width_absolute())
00127 this->set_abs_width(pObj->get_abs_width());
00128 else
00129 this->set_rel_width(pObj->get_rel_width());
00130 if (pObj->is_height_absolute())
00131 this->set_abs_height(pObj->get_abs_height());
00132 else
00133 this->set_rel_height(pObj->get_rel_height());
00134
00135 const std::map<anchor_point, anchor>& lanchorList = pObj->get_point_list();
00136 std::map<anchor_point, anchor>::const_iterator iterAnchor;
00137 foreach (iterAnchor, lanchorList)
00138 {
00139 if (iterAnchor->second.get_type() == ANCHOR_ABS)
00140 {
00141 this->set_abs_point(
00142 iterAnchor->second.get_point(),
00143 iterAnchor->second.get_parent_raw_name(),
00144 iterAnchor->second.get_parent_point(),
00145 iterAnchor->second.get_abs_offset_x(),
00146 iterAnchor->second.get_abs_offset_y()
00147 );
00148 }
00149 else
00150 {
00151 this->set_rel_point(
00152 iterAnchor->second.get_point(),
00153 iterAnchor->second.get_parent_raw_name(),
00154 iterAnchor->second.get_parent_point(),
00155 iterAnchor->second.get_rel_offset_x(),
00156 iterAnchor->second.get_rel_offset_y()
00157 );
00158 }
00159 }
00160 }
00161 }
00162
00163 const std::string& uiobject::get_name() const
00164 {
00165 return sName_;
00166 }
00167
00168 const std::string& uiobject::get_lua_name() const
00169 {
00170 return sLuaName_;
00171 }
00172
00173 const std::string& uiobject::get_raw_name() const
00174 {
00175 return sRawName_;
00176 }
00177
00178 void uiobject::set_name(const std::string& sName)
00179 {
00180 if (sName_.empty())
00181 {
00182 sName_ = sLuaName_ = sRawName_ = sName;
00183 if (utils::starts_with(sName_, "$parent"))
00184 {
00185 if (pParent_)
00186 utils::replace(sLuaName_, "$parent", pParent_->get_lua_name());
00187 else
00188 utils::replace(sLuaName_, "$parent", "");
00189 }
00190
00191 if (!bVirtual_)
00192 sName_ = sLuaName_;
00193 }
00194 else
00195 {
00196 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00197 << "set_name() can only be called once." << std::endl;
00198 }
00199 }
00200
00201 const std::string& uiobject::get_object_type() const
00202 {
00203 return lType_.back();
00204 }
00205
00206 const std::vector<std::string>& uiobject::get_object_typeList() const
00207 {
00208 return lType_;
00209 }
00210
00211 bool uiobject::is_object_type(const std::string& sType) const
00212 {
00213 return utils::find(lType_, sType) != lType_.end();
00214 }
00215
00216 float uiobject::get_alpha() const
00217 {
00218 return fAlpha_;
00219 }
00220
00221 void uiobject::set_alpha(float fAlpha)
00222 {
00223 if (fAlpha_ != fAlpha)
00224 {
00225 fAlpha_ = fAlpha;
00226 notify_renderer_need_redraw();
00227 }
00228 }
00229
00230 void uiobject::show()
00231 {
00232 bIsShown_ = true;
00233 }
00234
00235 void uiobject::hide()
00236 {
00237 bIsShown_ = false;
00238 }
00239
00240 void uiobject::set_shown(bool bIsShown)
00241 {
00242 bIsShown_ = bIsShown;
00243 }
00244
00245 bool uiobject::is_shown() const
00246 {
00247 return bIsShown_;
00248 }
00249
00250 bool uiobject::is_visible() const
00251 {
00252 return bIsVisible_;
00253 }
00254
00255 void uiobject::set_abs_width(uint uiAbsWidth)
00256 {
00257 if (uiAbsWidth_ != uiAbsWidth || !bIsWidthAbs_)
00258 {
00259 pManager_->notify_object_moved();
00260 bIsWidthAbs_ = true;
00261 uiAbsWidth_ = uiAbsWidth;
00262 fire_update_dimensions();
00263 notify_renderer_need_redraw();
00264 }
00265 }
00266
00267 void uiobject::set_abs_height(uint uiAbsHeight)
00268 {
00269 if (uiAbsHeight_ != uiAbsHeight || !bIsWidthAbs_)
00270 {
00271 pManager_->notify_object_moved();
00272 bIsHeightAbs_ = true;
00273 uiAbsHeight_ = uiAbsHeight;
00274 fire_update_dimensions();
00275 notify_renderer_need_redraw();
00276 }
00277 }
00278
00279 bool uiobject::is_width_absolute() const
00280 {
00281 return bIsWidthAbs_;
00282 }
00283
00284 bool uiobject::is_height_absolute() const
00285 {
00286 return bIsHeightAbs_;
00287 }
00288
00289 void uiobject::set_rel_width(float fRelWidth)
00290 {
00291 if (fRelWidth_ != fRelWidth || bIsWidthAbs_)
00292 {
00293 pManager_->notify_object_moved();
00294 bIsWidthAbs_ = false;
00295 fRelWidth_ = fRelWidth;
00296 fire_update_dimensions();
00297 notify_renderer_need_redraw();
00298 }
00299 }
00300
00301 void uiobject::set_rel_height(float fRelHeight)
00302 {
00303 if (fRelHeight_ != fRelHeight || bIsHeightAbs_)
00304 {
00305 pManager_->notify_object_moved();
00306 bIsHeightAbs_ = false;
00307 fRelHeight_ = fRelHeight;
00308 fire_update_dimensions();
00309 notify_renderer_need_redraw();
00310 }
00311 }
00312
00313 uint uiobject::get_abs_width() const
00314 {
00315 return uiAbsWidth_;
00316 }
00317
00318 uint uiobject::get_apparent_width() const
00319 {
00320 update_borders_();
00321 return uint(lBorderList_[BORDER_RIGHT] - lBorderList_[BORDER_LEFT]);
00322 }
00323
00324 uint uiobject::get_abs_height() const
00325 {
00326 return uiAbsHeight_;
00327 }
00328
00329 uint uiobject::get_apparent_height() const
00330 {
00331 update_borders_();
00332 return uint(lBorderList_[BORDER_BOTTOM] - lBorderList_[BORDER_TOP]);
00333 }
00334
00335 float uiobject::get_rel_width() const
00336 {
00337 return fRelWidth_;
00338 }
00339
00340 float uiobject::get_rel_height() const
00341 {
00342 return fRelHeight_;
00343 }
00344
00345 void uiobject::set_parent(uiobject* pParent)
00346 {
00347 if (pParent != this && pParent_ != pParent)
00348 {
00349 pParent_ = pParent;
00350 fire_update_dimensions();
00351 }
00352 else
00353 gui::out << gui::error << "gui::" << lType_.back() << " : Can't call set_parent(this)." << std::endl;
00354 }
00355
00356 const uiobject* uiobject::get_parent() const
00357 {
00358 return pParent_;
00359 }
00360
00361 uiobject* uiobject::get_parent()
00362 {
00363 return pParent_;
00364 }
00365
00366 uiobject* uiobject::get_base()
00367 {
00368 return pInheritance_;
00369 }
00370
00371 vector2<int> uiobject::get_center() const
00372 {
00373 update_borders_();
00374 return vector2<int>(
00375 lBorderList_[BORDER_LEFT] + int(uiAbsWidth_/2u),
00376 lBorderList_[BORDER_TOP] + int(uiAbsHeight_/2u)
00377 );
00378 }
00379
00380 int uiobject::get_left() const
00381 {
00382 update_borders_();
00383 return lBorderList_[BORDER_LEFT];
00384 }
00385
00386 int uiobject::get_right() const
00387 {
00388 update_borders_();
00389 return lBorderList_[BORDER_RIGHT];
00390 }
00391
00392 int uiobject::get_top() const
00393 {
00394 update_borders_();
00395 return lBorderList_[BORDER_TOP];
00396 }
00397
00398 int uiobject::get_bottom() const
00399 {
00400 update_borders_();
00401 return lBorderList_[BORDER_BOTTOM];
00402 }
00403
00404 const std::array<int,4>& uiobject::get_borders() const
00405 {
00406 return lBorderList_;
00407 }
00408
00409 void uiobject::clear_all_points()
00410 {
00411 if (lAnchorList_.size() != 0)
00412 {
00413 lAnchorList_.clear();
00414
00415 lDefinedBorderList_[BORDER_LEFT] =
00416 lDefinedBorderList_[BORDER_TOP] =
00417 lDefinedBorderList_[BORDER_RIGHT] =
00418 lDefinedBorderList_[BORDER_BOTTOM] = false;
00419
00420 bUpdateAnchors_ = true;
00421 fire_update_borders();
00422 notify_renderer_need_redraw();
00423 pManager_->notify_object_moved();
00424 }
00425 }
00426
00427 void uiobject::set_all_points(const std::string& sObjName)
00428 {
00429 if (sObjName != sName_)
00430 {
00431 clear_all_points();
00432 anchor mAnchor = anchor(this, ANCHOR_TOPLEFT, sObjName, ANCHOR_TOPLEFT);
00433 lAnchorList_[ANCHOR_TOPLEFT] = mAnchor;
00434
00435 mAnchor = anchor(this, ANCHOR_BOTTOMRIGHT, sObjName, ANCHOR_BOTTOMRIGHT);
00436 lAnchorList_[ANCHOR_BOTTOMRIGHT] = mAnchor;
00437
00438 lDefinedBorderList_[BORDER_LEFT] =
00439 lDefinedBorderList_[BORDER_TOP] =
00440 lDefinedBorderList_[BORDER_RIGHT] =
00441 lDefinedBorderList_[BORDER_BOTTOM] = true;
00442
00443 bUpdateAnchors_ = true;
00444 fire_update_borders();
00445 notify_renderer_need_redraw();
00446 pManager_->notify_object_moved();
00447 }
00448 else
00449 gui::out << gui::error << "gui::" << lType_.back() << " : Can't call set_all_points(this)." << std::endl;
00450 }
00451
00452 void uiobject::set_all_points(uiobject* pObj)
00453 {
00454 if (pObj != this)
00455 {
00456 clear_all_points();
00457 anchor mAnchor = anchor(this, ANCHOR_TOPLEFT, pObj ? pObj->get_name() : "", ANCHOR_TOPLEFT);
00458 lAnchorList_[ANCHOR_TOPLEFT] = mAnchor;
00459
00460 mAnchor = anchor(this, ANCHOR_BOTTOMRIGHT, pObj ? pObj->get_name() : "", ANCHOR_BOTTOMRIGHT);
00461 lAnchorList_[ANCHOR_BOTTOMRIGHT] = mAnchor;
00462
00463 lDefinedBorderList_[BORDER_LEFT] =
00464 lDefinedBorderList_[BORDER_TOP] =
00465 lDefinedBorderList_[BORDER_RIGHT] =
00466 lDefinedBorderList_[BORDER_BOTTOM] = true;
00467
00468 bUpdateAnchors_ = true;
00469 fire_update_borders();
00470 notify_renderer_need_redraw();
00471 pManager_->notify_object_moved();
00472 }
00473 else
00474 gui::out << gui::error << "gui::" << lType_.back() << " : Can't call set_all_points(this)." << std::endl;
00475 }
00476
00477 void uiobject::set_abs_point(anchor_point mPoint, const std::string& sParentName, anchor_point mRelativePoint, int iX, int iY)
00478 {
00479 std::map<anchor_point, anchor>::iterator iterAnchor = lAnchorList_.find(mPoint);
00480 if (iterAnchor == lAnchorList_.end())
00481 {
00482 anchor mAnchor = anchor(this, mPoint, sParentName, mRelativePoint);
00483 mAnchor.set_abs_offset(iX, iY);
00484 lAnchorList_[mPoint] = mAnchor;
00485 }
00486 else
00487 {
00488 anchor* pAnchor = &iterAnchor->second;
00489 pAnchor->set_parent_raw_name(sParentName);
00490 pAnchor->set_parent_point(mRelativePoint);
00491 pAnchor->set_abs_offset(iX, iY);
00492 }
00493
00494 switch (mPoint)
00495 {
00496 case ANCHOR_TOPLEFT :
00497 lDefinedBorderList_[BORDER_TOP] = true;
00498 lDefinedBorderList_[BORDER_LEFT] = true;
00499 break;
00500 case ANCHOR_TOP :
00501 lDefinedBorderList_[BORDER_TOP] = true;
00502 break;
00503 case ANCHOR_TOPRIGHT :
00504 lDefinedBorderList_[BORDER_TOP] = true;
00505 lDefinedBorderList_[BORDER_RIGHT] = true;
00506 break;
00507 case ANCHOR_RIGHT :
00508 lDefinedBorderList_[BORDER_RIGHT] = true;
00509 break;
00510 case ANCHOR_BOTTOMRIGHT :
00511 lDefinedBorderList_[BORDER_BOTTOM] = true;
00512 lDefinedBorderList_[BORDER_RIGHT] = true;
00513 break;
00514 case ANCHOR_BOTTOM :
00515 lDefinedBorderList_[BORDER_BOTTOM] = true;
00516 break;
00517 case ANCHOR_BOTTOMLEFT :
00518 lDefinedBorderList_[BORDER_BOTTOM] = true;
00519 lDefinedBorderList_[BORDER_LEFT] = true;
00520 break;
00521 case ANCHOR_LEFT :
00522 lDefinedBorderList_[BORDER_LEFT] = true;
00523 break;
00524 default : break;
00525 }
00526
00527 bUpdateAnchors_ = true;
00528 fire_update_borders();
00529 notify_renderer_need_redraw();
00530 pManager_->notify_object_moved();
00531 }
00532
00533 void uiobject::set_rel_point(anchor_point mPoint, const std::string& sParentName, anchor_point mRelativePoint, float fX, float fY)
00534 {
00535 std::map<anchor_point, anchor>::iterator iterAnchor = lAnchorList_.find(mPoint);
00536 if (iterAnchor == lAnchorList_.end())
00537 {
00538 anchor mAnchor = anchor(this, mPoint, sParentName, mRelativePoint);
00539 mAnchor.set_rel_offset(fX, fY);
00540 lAnchorList_[mPoint] = mAnchor;
00541 }
00542 else
00543 {
00544 anchor* pAnchor = &iterAnchor->second;
00545 pAnchor->set_parent_raw_name(sParentName);
00546 pAnchor->set_parent_point(mRelativePoint);
00547 pAnchor->set_rel_offset(fX, fY);
00548 }
00549
00550 switch (mPoint)
00551 {
00552 case ANCHOR_TOPLEFT :
00553 lDefinedBorderList_[BORDER_TOP] = true;
00554 lDefinedBorderList_[BORDER_LEFT] = true;
00555 break;
00556 case ANCHOR_TOP :
00557 lDefinedBorderList_[BORDER_TOP] = true;
00558 break;
00559 case ANCHOR_TOPRIGHT :
00560 lDefinedBorderList_[BORDER_TOP] = true;
00561 lDefinedBorderList_[BORDER_RIGHT] = true;
00562 break;
00563 case ANCHOR_RIGHT :
00564 lDefinedBorderList_[BORDER_RIGHT] = true;
00565 break;
00566 case ANCHOR_BOTTOMRIGHT :
00567 lDefinedBorderList_[BORDER_BOTTOM] = true;
00568 lDefinedBorderList_[BORDER_RIGHT] = true;
00569 break;
00570 case ANCHOR_BOTTOM :
00571 lDefinedBorderList_[BORDER_BOTTOM] = true;
00572 break;
00573 case ANCHOR_BOTTOMLEFT :
00574 lDefinedBorderList_[BORDER_BOTTOM] = true;
00575 lDefinedBorderList_[BORDER_LEFT] = true;
00576 break;
00577 case ANCHOR_LEFT :
00578 lDefinedBorderList_[BORDER_LEFT] = true;
00579 break;
00580 default : break;
00581 }
00582
00583 bUpdateAnchors_ = true;
00584 fire_update_borders();
00585 notify_renderer_need_redraw();
00586 pManager_->notify_object_moved();
00587 }
00588
00589 void uiobject::set_point(const anchor& mAnchor)
00590 {
00591 lAnchorList_[mAnchor.get_point()] = mAnchor;
00592
00593 switch (mAnchor.get_point())
00594 {
00595 case ANCHOR_TOPLEFT :
00596 lDefinedBorderList_[BORDER_TOP] = true;
00597 lDefinedBorderList_[BORDER_LEFT] = true;
00598 break;
00599 case ANCHOR_TOP :
00600 lDefinedBorderList_[BORDER_TOP] = true;
00601 break;
00602 case ANCHOR_TOPRIGHT :
00603 lDefinedBorderList_[BORDER_TOP] = true;
00604 lDefinedBorderList_[BORDER_RIGHT] = true;
00605 break;
00606 case ANCHOR_RIGHT :
00607 lDefinedBorderList_[BORDER_RIGHT] = true;
00608 break;
00609 case ANCHOR_BOTTOMRIGHT :
00610 lDefinedBorderList_[BORDER_BOTTOM] = true;
00611 lDefinedBorderList_[BORDER_RIGHT] = true;
00612 break;
00613 case ANCHOR_BOTTOM :
00614 lDefinedBorderList_[BORDER_BOTTOM] = true;
00615 break;
00616 case ANCHOR_BOTTOMLEFT :
00617 lDefinedBorderList_[BORDER_BOTTOM] = true;
00618 lDefinedBorderList_[BORDER_LEFT] = true;
00619 break;
00620 case ANCHOR_LEFT :
00621 lDefinedBorderList_[BORDER_LEFT] = true;
00622 break;
00623 default : break;
00624 }
00625
00626 bUpdateAnchors_ = true;
00627 fire_update_borders();
00628 notify_renderer_need_redraw();
00629 pManager_->notify_object_moved();
00630 }
00631
00632 bool uiobject::depends_on(uiobject* pObj) const
00633 {
00634 if (pObj)
00635 {
00636 std::map<anchor_point, anchor>::const_iterator iterAnchor;
00637 foreach (iterAnchor, lAnchorList_)
00638 {
00639 const uiobject* pParent = iterAnchor->second.get_parent();
00640 if (pParent == pObj)
00641 return true;
00642
00643 if (pParent)
00644 return pParent->depends_on(pObj);
00645 }
00646 }
00647
00648 return false;
00649 }
00650
00651 uint uiobject::get_num_point() const
00652 {
00653 return lAnchorList_.size();
00654 }
00655
00656 anchor* uiobject::modify_point(anchor_point mPoint)
00657 {
00658 pManager_->notify_object_moved();
00659
00660 fire_update_borders();
00661
00662 std::map<anchor_point, anchor>::iterator iterAnchor = lAnchorList_.find(mPoint);
00663 if (iterAnchor != lAnchorList_.end())
00664 return &iterAnchor->second;
00665 else
00666 return nullptr;
00667 }
00668
00669 const anchor* uiobject::get_point(anchor_point mPoint) const
00670 {
00671 std::map<anchor_point, anchor>::const_iterator iterAnchor = lAnchorList_.find(mPoint);
00672 if (iterAnchor != lAnchorList_.end())
00673 return &iterAnchor->second;
00674 else
00675 return nullptr;
00676 }
00677
00678 const std::map<anchor_point, anchor>& uiobject::get_point_list() const
00679 {
00680 return lAnchorList_;
00681 }
00682
00683 bool uiobject::is_virtual() const
00684 {
00685 return bVirtual_;
00686 }
00687
00688 void uiobject::set_virtual()
00689 {
00690 bVirtual_ = true;
00691 }
00692
00693 uint uiobject::get_id() const
00694 {
00695 return uiID_;
00696 }
00697
00698 void uiobject::set_id(uint uiID)
00699 {
00700 if (uiID_ == uint(-1))
00701 uiID_ = uiID;
00702 else
00703 gui::out << gui::warning << "gui::" << lType_.back() << " : set_id() can't be called more than once." << std::endl;
00704 }
00705
00706 void uiobject::notify_anchored_object(uiobject* pObj, bool bAnchored) const
00707 {
00708 if (!pObj)
00709 return;
00710
00711 if (bAnchored)
00712 {
00713 if (lAnchoredObjectList_.find(pObj->get_id()) == lAnchoredObjectList_.end())
00714 lAnchoredObjectList_[pObj->get_id()] = pObj;
00715 }
00716 else
00717 lAnchoredObjectList_.erase(pObj->get_id());
00718 }
00719
00720 void uiobject::update_dimensions_() const
00721 {
00722 if (pParent_)
00723 {
00724 if (bIsHeightAbs_)
00725 fRelHeight_ = float(uiAbsHeight_)/float(pParent_->get_apparent_height());
00726 else
00727 uiAbsHeight_ = fRelHeight_*pParent_->get_apparent_height();
00728
00729 if (bIsWidthAbs_)
00730 fRelWidth_ = float(uiAbsWidth_)/float(pParent_->get_apparent_width());
00731 else
00732 uiAbsWidth_ = fRelWidth_*pParent_->get_apparent_width();
00733 }
00734 else
00735 {
00736 if (bIsHeightAbs_)
00737 fRelHeight_ = float(uiAbsHeight_)/float(pManager_->get_screen_height());
00738 else
00739 uiAbsHeight_ = fRelHeight_*pManager_->get_screen_height();
00740
00741 if (bIsWidthAbs_)
00742 fRelWidth_ = float(uiAbsWidth_)/float(pManager_->get_screen_width());
00743 else
00744 uiAbsWidth_ = fRelWidth_*pManager_->get_screen_width();
00745 }
00746 }
00747
00748 void uiobject::make_borders_(float& iMin, float& iMax, float iCenter, float iSize) const
00749 {
00750 if (std::isinf(iMin) && std::isinf(iMax))
00751 {
00752 if (!std::isinf(iSize) && iSize != 0 && !std::isinf(iCenter))
00753 {
00754 iMin = iCenter - iSize/2.0f;
00755 iMax = iCenter + iSize/2.0f;
00756 }
00757 else
00758 bReady_ = false;
00759 }
00760 else if (std::isinf(iMax))
00761 {
00762 if (!std::isinf(iSize) && iSize != 0)
00763 iMax = iMin + iSize;
00764 else if (!std::isinf(iCenter))
00765 iMax = iMin + 2.0f*(iCenter - iMin);
00766 else
00767 bReady_ = false;
00768 }
00769 else if (std::isinf(iMin))
00770 {
00771 if (!std::isinf(iSize) && iSize != 0)
00772 iMin = iMax - iSize;
00773 else if (!std::isinf(iCenter))
00774 iMin = iMax - 2.0f*(iMax - iCenter);
00775 else
00776 bReady_ = false;
00777 }
00778 }
00779
00780 void uiobject::read_anchors_(float& iLeft, float& iRight, float& iTop,
00781 float& iBottom, float& iXCenter, float& iYCenter) const
00782 {
00783 iLeft = +std::numeric_limits<float>::infinity();
00784 iRight = -std::numeric_limits<float>::infinity();
00785 iTop = +std::numeric_limits<float>::infinity();
00786 iBottom = -std::numeric_limits<float>::infinity();
00787
00788 std::map<anchor_point, anchor>::const_iterator iterAnchor;
00789 foreach (iterAnchor, lAnchorList_)
00790 {
00791
00792 const uiobject* pObj = iterAnchor->second.get_parent();
00793 if (pObj)
00794 pObj->update_borders_();
00795
00796 switch (iterAnchor->second.get_point())
00797 {
00798 case ANCHOR_TOPLEFT :
00799 iTop = std::min<float>(iTop, iterAnchor->second.get_abs_y());
00800 iLeft = std::min<float>(iLeft, iterAnchor->second.get_abs_x());
00801 break;
00802 case ANCHOR_TOP :
00803 iTop = std::min<float>(iTop, iterAnchor->second.get_abs_y());
00804 iXCenter = iterAnchor->second.get_abs_x();
00805 break;
00806 case ANCHOR_TOPRIGHT :
00807 iTop = std::min<float>(iTop, iterAnchor->second.get_abs_y());
00808 iRight = std::max<float>(iRight, iterAnchor->second.get_abs_x());
00809 break;
00810 case ANCHOR_RIGHT :
00811 iRight = std::max<float>(iRight, iterAnchor->second.get_abs_x());
00812 iYCenter = iterAnchor->second.get_abs_y();
00813 break;
00814 case ANCHOR_BOTTOMRIGHT :
00815 iBottom = std::max<float>(iBottom, iterAnchor->second.get_abs_y());
00816 iRight = std::max<float>(iRight, iterAnchor->second.get_abs_x());
00817 break;
00818 case ANCHOR_BOTTOM :
00819 iBottom = std::max<float>(iBottom, iterAnchor->second.get_abs_y());
00820 iXCenter = iterAnchor->second.get_abs_x();
00821 break;
00822 case ANCHOR_BOTTOMLEFT :
00823 iBottom = std::max<float>(iBottom, iterAnchor->second.get_abs_y());
00824 iLeft = std::min<float>(iLeft, iterAnchor->second.get_abs_x());
00825 break;
00826 case ANCHOR_LEFT :
00827 iLeft = std::min<float>(iLeft, iterAnchor->second.get_abs_x());
00828 iYCenter = iterAnchor->second.get_abs_y();
00829 break;
00830 case ANCHOR_CENTER :
00831 iXCenter = iterAnchor->second.get_abs_x();
00832 iYCenter = iterAnchor->second.get_abs_y();
00833 break;
00834 }
00835 }
00836 }
00837
00838 void uiobject::update_borders_() const
00839 {
00840 if (!bUpdateBorders_)
00841 return;
00842
00843
00844 #define DEBUG_LOG(msg)
00845
00846 bool bOldReady = bReady_;
00847 bReady_ = true;
00848
00849 if (bUpdateDimensions_)
00850 {
00851 DEBUG_LOG(" Update dimentions");
00852 update_dimensions_();
00853 bUpdateDimensions_ = false;
00854 }
00855
00856 if (!lAnchorList_.empty())
00857 {
00858 float fLeft = 0.0f, fRight = 0.0f, fTop = 0.0f, fBottom = 0.0f;
00859 float fXCenter = 0.0f, fYCenter = 0.0f;
00860
00861 DEBUG_LOG(" Read anchors");
00862 read_anchors_(fLeft, fRight, fTop, fBottom, fXCenter, fYCenter);
00863
00864 DEBUG_LOG(" Make borders");
00865 make_borders_(fTop, fBottom, fYCenter, uiAbsHeight_);
00866 make_borders_(fLeft, fRight, fXCenter, uiAbsWidth_);
00867
00868 if (bReady_)
00869 {
00870 int iLeft = fLeft, iRight = fRight, iTop = fTop, iBottom = fBottom;
00871
00872 if (iRight < iLeft)
00873 iRight = iLeft+1;
00874 if (iBottom < iTop)
00875 iBottom = iTop+1;
00876
00877 lBorderList_[BORDER_LEFT] = iLeft;
00878 lBorderList_[BORDER_RIGHT] = iRight;
00879 lBorderList_[BORDER_TOP] = iTop;
00880 lBorderList_[BORDER_BOTTOM] = iBottom;
00881
00882 bIsWidthAbs_ = true;
00883 uiAbsWidth_ = iRight - iLeft;
00884
00885 bIsHeightAbs_ = true;
00886 uiAbsHeight_ = iBottom - iTop;
00887
00888 DEBUG_LOG(" Update dimentions");
00889 update_dimensions_();
00890 }
00891 else
00892 lBorderList_ = {{0, 0, 0, 0}};
00893
00894 bUpdateBorders_ = false;
00895 }
00896 else
00897 bReady_ = false;
00898
00899 if (bReady_ || (!bReady_ && bOldReady))
00900 {
00901 DEBUG_LOG(" Fire redraw");
00902 notify_renderer_need_redraw();
00903 }
00904 DEBUG_LOG(" @");
00905 }
00906
00907 void uiobject::update_anchors()
00908 {
00909 if (bUpdateAnchors_)
00910 {
00911 std::vector<std::map<anchor_point, anchor>::iterator> lEraseList;
00912 std::map<anchor_point, anchor>::iterator iterAnchor;
00913 foreach (iterAnchor, lAnchorList_)
00914 {
00915 const uiobject* pObj = iterAnchor->second.get_parent();
00916 if (pObj && pObj->depends_on(this))
00917 {
00918 gui::out << gui::error << "gui::" << lType_.back() << " : Cyclic anchor dependency !"
00919 << "\"" << sName_ << "\" and \"" << pObj->get_name() << "\" depend on"
00920 "eachothers (directly or indirectly).\n\""
00921 << anchor::get_string_point(iterAnchor->first) << "\" anchor removed." << std::endl;
00922
00923 lEraseList.push_back(iterAnchor);
00924 }
00925 }
00926
00927 std::vector<std::map<anchor_point, anchor>::iterator>::iterator iterErase;
00928 foreach (iterErase, lEraseList)
00929 lAnchorList_.erase(*iterErase);
00930
00931 std::vector<const uiobject*> lAnchorParentList;
00932 foreach (iterAnchor, lAnchorList_)
00933 {
00934 const uiobject* pParent = iterAnchor->second.get_parent();
00935 if (pParent && utils::find(lAnchorParentList, pParent) == lAnchorParentList.end())
00936 lAnchorParentList.push_back(pParent);
00937 }
00938
00939 std::vector<const uiobject*>::iterator iterOldParent;
00940 foreach (iterOldParent, lPreviousAnchorParentList_)
00941 {
00942 const uiobject* pParent = *iterOldParent;
00943 if (utils::find(lAnchorParentList, pParent) == lAnchorParentList.end())
00944 pParent->notify_anchored_object(this, false);
00945 }
00946
00947 std::vector<const uiobject*>::iterator iterParent;
00948 foreach (iterParent, lAnchorParentList)
00949 {
00950 const uiobject* pParent = *iterParent;
00951 if (utils::find(lPreviousAnchorParentList_, pParent) == lPreviousAnchorParentList_.end())
00952 pParent->notify_anchored_object(this, true);
00953 }
00954
00955 lPreviousAnchorParentList_ = lAnchorParentList;
00956 bUpdateAnchors_ = false;
00957 }
00958 }
00959
00960 void uiobject::fire_update_borders() const
00961 {
00962 bUpdateBorders_ = true;
00963
00964 std::map<uint, uiobject*>::const_iterator iterAnchored;
00965 foreach (iterAnchored, lAnchoredObjectList_)
00966 iterAnchored->second->fire_update_borders();
00967 }
00968
00969 void uiobject::fire_update_dimensions() const
00970 {
00971 fire_update_borders();
00972 bUpdateDimensions_ = true;
00973 }
00974
00975 void uiobject::update(float fDelta)
00976 {
00977
00978 #define DEBUG_LOG(msg)
00979 DEBUG_LOG(" Update " + sName_ + " (" + lType_.back() + ")");
00980 update_borders_();
00981
00982 if (bNewlyCreated_)
00983 {
00984 bNewlyCreated_ = false;
00985 DEBUG_LOG(" Fire redraw");
00986 notify_renderer_need_redraw();
00987 }
00988 DEBUG_LOG(" +");
00989 }
00990
00991 void uiobject::push_on_lua(lua::state* pLua) const
00992 {
00993 pLua->push_global(sLuaName_);
00994 }
00995
00996 void uiobject::remove_glue()
00997 {
00998 utils::wptr<lua::state> pLua = pManager_->get_lua();
00999 pLua->push_nil();
01000 pLua->set_global(sLuaName_);
01001 }
01002
01003 void uiobject::set_special()
01004 {
01005 bSpecial_ = true;
01006 }
01007
01008 bool uiobject::is_special() const
01009 {
01010 return bSpecial_;
01011 }
01012
01013 void uiobject::set_manually_rendered(bool bManuallyRendered, uiobject* pRenderer)
01014 {
01015 uiobject* pOldrenderer = pRenderer_;
01016
01017 if (pOldrenderer && pOldrenderer != pRenderer)
01018 pOldrenderer->notify_manually_rendered_object_(this, false);
01019
01020 notify_renderer_need_redraw();
01021
01022 bManuallyRendered_ = bManuallyRendered;
01023 if (bManuallyRendered_)
01024 pRenderer_ = pRenderer;
01025 else
01026 pRenderer_ = nullptr;
01027
01028 if (pRenderer_ && pRenderer_ != pOldrenderer && bManuallyRendered_)
01029 pRenderer_->notify_manually_rendered_object_(this, true);
01030
01031 notify_renderer_need_redraw();
01032 }
01033
01034 bool uiobject::is_manually_rendered() const
01035 {
01036 return bManuallyRendered_;
01037 }
01038
01039 void uiobject::set_newly_created()
01040 {
01041 bNewlyCreated_ = true;
01042 }
01043
01044 bool uiobject::is_newly_created() const
01045 {
01046 return bNewlyCreated_;
01047 }
01048
01049 void uiobject::notify_renderer_need_redraw() const
01050 {
01051 }
01052
01053 void uiobject::fire_redraw() const
01054 {
01055 }
01056
01057 void uiobject::notify_manually_rendered_object_(uiobject* pObject, bool bManuallyRendered)
01058 {
01059 }
01060
01061 void uiobject::mark_for_copy(const std::string& sVariable)
01062 {
01063 if (utils::find(lCopyList_, sVariable) == lCopyList_.end())
01064 lCopyList_.push_back(sVariable);
01065 else
01066 {
01067 gui::out << gui::warning << "gui::" << lType_.back() << " : "
01068 << "\"" << sName_ << "." << sVariable << "\" has already been marked for copy. Ignoring." << std::endl;
01069 }
01070 }
01071
01072 std::map<uint, uiobject*> uiobject::get_anchored_objects() const
01073 {
01074 return lAnchoredObjectList_;
01075 }
01076
01077 std::vector<uiobject*> uiobject::clear_links()
01078 {
01079
01080 if (pParent_)
01081 {
01082 frame* pParentFrame = dynamic_cast<frame*>(pParent_);
01083 frame* pThisFrame = dynamic_cast<frame*>(this);
01084 if (pThisFrame)
01085 pParentFrame->remove_child(pThisFrame);
01086 else
01087 {
01088 layered_region* pThisRegion = dynamic_cast<layered_region*>(this);
01089 if (pThisRegion)
01090 pParentFrame->remove_region(pThisRegion);
01091 }
01092 pParent_ = nullptr;
01093 }
01094
01095 notify_renderer_need_redraw();
01096
01097
01098 if (bManuallyRendered_ && pRenderer_)
01099 pRenderer_->notify_manually_rendered_object_(this, false);
01100
01101
01102 std::map<anchor_point, anchor>::const_iterator iterAnchor;
01103 foreach (iterAnchor, lAnchorList_)
01104 {
01105 if (iterAnchor->second.get_parent())
01106 iterAnchor->second.get_parent()->notify_anchored_object(this, false);
01107 }
01108
01109 lAnchorList_.clear();
01110
01111
01112 std::map<uint, uiobject*>::iterator iterAnchored;
01113 std::map<uint, uiobject*> lTempAnchoredObjectList = lAnchoredObjectList_;
01114 foreach (iterAnchored, lTempAnchoredObjectList)
01115 {
01116 uiobject* pObj = iterAnchored->second;
01117 std::vector<anchor_point> lAnchoredPointList;
01118 const std::map<anchor_point, anchor>& lanchorList = pObj->get_point_list();
01119 std::map<anchor_point, anchor>::const_iterator iterAnchor;
01120 foreach (iterAnchor, lanchorList)
01121 {
01122 if (iterAnchor->second.get_parent() == this)
01123 lAnchoredPointList.push_back(iterAnchor->first);
01124 }
01125
01126 std::vector<anchor_point>::iterator iterAnchor_point;
01127 foreach (iterAnchor_point, lAnchoredPointList)
01128 {
01129 const anchor* pAnchor = pObj->get_point(*iterAnchor_point);
01130 anchor mNewAnchor = anchor(pObj, *iterAnchor_point, "", ANCHOR_TOPLEFT);
01131
01132 int iX = pAnchor->get_abs_offset_x();
01133 int iY = pAnchor->get_abs_offset_y();
01134
01135 switch (pAnchor->get_parent_point())
01136 {
01137 case ANCHOR_TOPLEFT :
01138 iX += lBorderList_[BORDER_LEFT];
01139 iY += lBorderList_[BORDER_TOP];
01140 break;
01141
01142 case ANCHOR_TOP :
01143 iY += lBorderList_[BORDER_TOP];
01144 break;
01145
01146 case ANCHOR_TOPRIGHT :
01147 iX += lBorderList_[BORDER_RIGHT];
01148 iY += lBorderList_[BORDER_TOP];
01149 break;
01150
01151 case ANCHOR_RIGHT :
01152 iX += lBorderList_[BORDER_RIGHT];
01153 break;
01154
01155 case ANCHOR_BOTTOMRIGHT :
01156 iX += lBorderList_[BORDER_RIGHT];
01157 iY += lBorderList_[BORDER_BOTTOM];
01158 break;
01159
01160 case ANCHOR_BOTTOM :
01161 iY += lBorderList_[BORDER_BOTTOM];
01162 break;
01163
01164 case ANCHOR_BOTTOMLEFT :
01165 iX += lBorderList_[BORDER_LEFT];
01166 iY += lBorderList_[BORDER_BOTTOM];
01167 break;
01168
01169 case ANCHOR_LEFT :
01170 iX += lBorderList_[BORDER_LEFT];
01171 break;
01172
01173 case ANCHOR_CENTER :
01174 iX += (lBorderList_[BORDER_LEFT] + lBorderList_[BORDER_RIGHT])/2;
01175 iY += (lBorderList_[BORDER_TOP] + lBorderList_[BORDER_BOTTOM])/2;
01176 }
01177
01178 mNewAnchor.set_abs_offset(iX, iY);
01179
01180 pObj->set_point(mNewAnchor);
01181 }
01182
01183 pObj->update_anchors();
01184 }
01185
01186 std::vector<uiobject*> lList;
01187 lList.push_back(this);
01188
01189 return lList;
01190 }
01191
01192 void uiobject::notify_loaded()
01193 {
01194 bLoaded_ = true;
01195 }
01196 }