00001
00002
00003
00004
00005
00006 #include "gui_frame.hpp"
00007
00008 #include "gui_layeredregion.hpp"
00009 #include "gui_manager.hpp"
00010 #include "gui_backdrop.hpp"
00011 #include "gui_event.hpp"
00012 #include "gui_eventmanager.hpp"
00013 #include "gui_out.hpp"
00014
00015 #include <utils_string.hpp>
00016 #include <sstream>
00017 #include <functional>
00018
00019 namespace gui
00020 {
00021 int l_xml_error(lua_State*);
00022
00023 frame::frame(manager* pManager) : event_receiver(pManager->get_event_manager().lock().get()),
00024 region(pManager), pAddOn_(nullptr), iLevel_(0), mStrata_(STRATA_MEDIUM), bIsTopLevel_(false),
00025 pTopLevelParent_(nullptr), bHasAllEventsRegistred_(false), bIsKeyboardEnabled_(false),
00026 bIsMouseEnabled_(false), bAllowWorldInput_(false), bIsMouseWheelEnabled_(false),
00027 bIsMovable_(false), bIsClampedToScreen_(false), bIsResizable_(false), bIsUserPlaced_(false),
00028 bBuildLayerList_(false), lAbsHitRectInsetList_({{0, 0, 0, 0}}),
00029 lRelHitRectInsetList_({{0.0f, 0.0f, 0.0f, 0.0f}}), uiMinWidth_(0u), uiMaxWidth_(uint(-1)),
00030 uiMinHeight_(0u), uiMaxHeight_(uint(-1)), fScale_(1.0f), bMouseInFrame_(false),
00031 bMouseInTitleRegion_(false), iMousePosX_(0), iMousePosY_(0), pTitleRegion_(nullptr),
00032 pParentFrame_(nullptr), bMouseDragged_(false)
00033 {
00034 lType_.push_back("Frame");
00035 }
00036
00037 frame::~frame()
00038 {
00039 std::map<uint, layered_region*>::iterator iterRegion;
00040 foreach (iterRegion, lRegionList_)
00041 delete iterRegion->second;
00042
00043 std::map<uint, frame*>::iterator iterChild;
00044 foreach (iterChild, lChildList_)
00045 delete iterChild->second;
00046
00047 delete pTitleRegion_;
00048 }
00049
00050 void frame::render()
00051 {
00052 if (bIsVisible_ && bReady_)
00053 {
00054 if (pBackdrop_)
00055 pBackdrop_->render();
00056
00057
00058 std::map<layer_type, layer>::iterator iterLayer;
00059 foreach (iterLayer, lLayerList_)
00060 {
00061 layer& mLayer = iterLayer->second;
00062 if (!mLayer.bDisabled)
00063 {
00064 std::vector<layered_region*>::iterator iterRegion;
00065 foreach (iterRegion, mLayer.lRegionList)
00066 {
00067 layered_region* pRegion = *iterRegion;
00068 if (pRegion->is_shown() && !pRegion->is_manually_rendered() && !pRegion->is_newly_created())
00069 pRegion->render();
00070 }
00071 }
00072 }
00073 }
00074 }
00075
00076 void frame::create_glue()
00077 {
00078 if (bVirtual_)
00079 {
00080 utils::wptr<lua::state> pLua = pManager_->get_lua();
00081 pLua->push_number(uiID_);
00082 lGlueList_.push_back(pLua->push_new<lua_virtual_glue>());
00083 pLua->set_global(sLuaName_);
00084 pLua->pop();
00085 }
00086 else
00087 {
00088 utils::wptr<lua::state> pLua = pManager_->get_lua();
00089 pLua->push_string(sName_);
00090 lGlueList_.push_back(pLua->push_new<lua_frame>());
00091 pLua->set_global(sLuaName_);
00092 pLua->pop();
00093 }
00094 }
00095
00096 std::string frame::serialize(const std::string& sTab) const
00097 {
00098 std::ostringstream sStr;
00099
00100 sStr << region::serialize(sTab);
00101 sStr << sTab << " # Strata : ";
00102 switch (mStrata_)
00103 {
00104 case STRATA_PARENT : sStr << "PARENT\n"; break;
00105 case STRATA_BACKGROUND : sStr << "BACKGROUND\n"; break;
00106 case STRATA_LOW : sStr << "LOW\n"; break;
00107 case STRATA_MEDIUM : sStr << "MEDIUM\n"; break;
00108 case STRATA_HIGH : sStr << "HIGH\n"; break;
00109 case STRATA_DIALOG : sStr << "DIALOG\n"; break;
00110 case STRATA_FULLSCREEN : sStr << "FULLSCREEN\n"; break;
00111 case STRATA_FULLSCREEN_DIALOG : sStr << "FULLSCREEN_DIALOG\n"; break;
00112 case STRATA_TOOLTIP : sStr << "TOOLTIP\n"; break;
00113 }
00114 sStr << sTab << " # Level : " << iLevel_ << "\n";
00115 sStr << sTab << " # TopLevel : " << bIsTopLevel_;
00116 if (!bIsTopLevel_ && pTopLevelParent_)
00117 sStr << " (" << pTopLevelParent_->get_name() << ")\n";
00118 else
00119 sStr << "\n";
00120 if (!bIsMouseEnabled_ && !bIsKeyboardEnabled_ && !bIsMouseWheelEnabled_)
00121 sStr << sTab << " # Inputs : none\n";
00122 else
00123 {
00124 sStr << sTab << " # Inputs :\n";
00125 sStr << sTab << " |-###\n";
00126 if (bIsMouseEnabled_)
00127 sStr << sTab << " | # mouse\n";
00128 if (bIsKeyboardEnabled_)
00129 sStr << sTab << " | # keyboard\n";
00130 if (bIsMouseWheelEnabled_)
00131 sStr << sTab << " | # mouse wheel\n";
00132 sStr << sTab << " |-###\n";
00133 }
00134 sStr << sTab << " # Movable : " << bIsMovable_ << "\n";
00135 sStr << sTab << " # Resizable : " << bIsResizable_ << "\n";
00136 sStr << sTab << " # Clamped : " << bIsClampedToScreen_ << "\n";
00137 sStr << sTab << " # HRect inset :\n";
00138 sStr << sTab << " |-###\n";
00139 sStr << sTab << " | # left : " << lAbsHitRectInsetList_[BORDER_LEFT] << "\n";
00140 sStr << sTab << " | # right : " << lAbsHitRectInsetList_[BORDER_RIGHT] << "\n";
00141 sStr << sTab << " | # top : " << lAbsHitRectInsetList_[BORDER_TOP] << "\n";
00142 sStr << sTab << " | # bottom : " << lAbsHitRectInsetList_[BORDER_BOTTOM] << "\n";
00143 sStr << sTab << " |-###\n";
00144 sStr << sTab << " # Min width : " << uiMinWidth_ << "\n";
00145 sStr << sTab << " # Max width : " << uiMaxWidth_ << "\n";
00146 sStr << sTab << " # Min height : " << uiMinHeight_ << "\n";
00147 sStr << sTab << " # Max height : " << uiMaxHeight_ << "\n";
00148 sStr << sTab << " # Scale : " << fScale_ << "\n";
00149 if (pTitleRegion_)
00150 {
00151 sStr << sTab << " # Title reg. :\n";
00152 sStr << sTab << " |-###\n";
00153 sStr << pTitleRegion_->serialize(sTab+" | ");
00154 sStr << sTab << " |-###\n";
00155 }
00156 if (pBackdrop_)
00157 {
00158 const std::array<int,4>& lInsets = pBackdrop_->get_background_insets();
00159
00160 sStr << sTab << " # Backdrop :\n";
00161 sStr << sTab << " |-###\n";
00162 sStr << sTab << " | # Background : " << pBackdrop_->get_background_file() << "\n";
00163 sStr << sTab << " | # Tilling : " << pBackdrop_->is_background_tilling() << "\n";
00164 if (pBackdrop_->is_background_tilling())
00165 sStr << sTab << " | # Tile size : " << pBackdrop_->get_tile_size() << "\n";
00166 sStr << sTab << " | # BG Insets :\n";
00167 sStr << sTab << " | |-###\n";
00168 sStr << sTab << " | | # left : " << lInsets[BORDER_LEFT] << "\n";
00169 sStr << sTab << " | | # right : " << lInsets[BORDER_RIGHT] << "\n";
00170 sStr << sTab << " | | # top : " << lInsets[BORDER_TOP] << "\n";
00171 sStr << sTab << " | | # bottom : " << lInsets[BORDER_BOTTOM] << "\n";
00172 sStr << sTab << " | |-###\n";
00173 sStr << sTab << " | # Edge : " << pBackdrop_->get_edge_file() << "\n";
00174 sStr << sTab << " | # Edge size : " << pBackdrop_->get_edge_size() << "\n";
00175 sStr << sTab << " |-###\n";
00176 }
00177
00178 if (!lRegionList_.empty())
00179 {
00180 if (lChildList_.size() == 1)
00181 sStr << sTab << " # Region : \n";
00182 else
00183 sStr << sTab << " # Regions : " << lRegionList_.size() << "\n";
00184 sStr << sTab << " |-###\n";
00185
00186 std::map<uint, layered_region*>::const_iterator iterRegion;
00187 foreach (iterRegion, lRegionList_)
00188 {
00189 sStr << iterRegion->second->serialize(sTab+" | ");
00190 sStr << sTab << " |-###\n";
00191 }
00192 }
00193
00194 if (!lChildList_.empty())
00195 {
00196 if (lChildList_.size() == 1)
00197 sStr << sTab << " # Child : \n";
00198 else
00199 sStr << sTab << " # Children : " << lChildList_.size() << "\n";
00200 sStr << sTab << " |-###\n";
00201
00202 std::map<uint, frame*>::const_iterator iterChild;
00203 foreach (iterChild, lChildList_)
00204 {
00205 sStr << iterChild->second->serialize(sTab+" | ");
00206 sStr << sTab << " |-###\n";
00207 }
00208 }
00209
00210 return sStr.str();
00211 }
00212
00213 bool frame::can_use_script(const std::string& sScriptName) const
00214 {
00215 if ((sScriptName == "OnDragStart") ||
00216 (sScriptName == "OnDragStop") ||
00217 (sScriptName == "OnEnter") ||
00218 (sScriptName == "OnEvent") ||
00219 (sScriptName == "OnHide") ||
00220 (sScriptName == "OnKeyDown") ||
00221 (sScriptName == "OnKeyUp") ||
00222 (sScriptName == "OnLeave") ||
00223 (sScriptName == "OnLoad") ||
00224 (sScriptName == "OnMouseDown") ||
00225 (sScriptName == "OnMouseUp") ||
00226 (sScriptName == "OnMouseWheel") ||
00227 (sScriptName == "OnReceiveDrag") ||
00228 (sScriptName == "OnShow") ||
00229 (sScriptName == "OnSizeChanged") ||
00230 (sScriptName == "OnUpdate"))
00231 return true;
00232 else
00233 return false;
00234 }
00235
00236 void frame::copy_from(uiobject* pObj)
00237 {
00238 uiobject::copy_from(pObj);
00239
00240 frame* pFrame = dynamic_cast<frame*>(pObj);
00241
00242 if (pFrame)
00243 {
00244 std::map<std::string, std::string>::const_iterator iterScript;
00245 foreach (iterScript, pFrame->lDefinedScriptList_)
00246 {
00247 if (!iterScript->second.empty())
00248 {
00249 script_info mInfo = pFrame->lXMLScriptInfoList_[iterScript->first];
00250 this->define_script(
00251 "On"+iterScript->first, iterScript->second,
00252 mInfo.sFile, mInfo.uiLineNbr
00253 );
00254 }
00255 }
00256
00257 std::map<std::string, handler>::const_iterator iterHandler;
00258 foreach (iterHandler, pFrame->lDefinedHandlerList_)
00259 {
00260 if (iterHandler->second)
00261 this->define_script("On"+iterHandler->first, iterHandler->second);
00262 }
00263
00264 this->set_frame_strata(pFrame->get_frame_strata());
00265
00266 uiobject* pHighParent = this;
00267 for (int i = 0; i < pFrame->get_frame_level(); ++i)
00268 {
00269 if (pHighParent->get_parent())
00270 pHighParent = pHighParent->get_parent();
00271 else
00272 break;
00273 }
00274
00275 this->set_level(
00276 dynamic_cast<frame*>(pHighParent)->get_frame_level()+
00277 pFrame->get_frame_level()
00278 );
00279
00280 this->set_top_level(pFrame->is_top_level());
00281
00282 this->enable_keyboard(pFrame->is_keyboard_enabled());
00283 this->enable_mouse(pFrame->is_mouse_enabled(), pFrame->is_world_input_allowed());
00284 this->enable_mouse_wheel(pFrame->is_mouse_wheel_enabled());
00285
00286 this->set_movable(pFrame->is_movable());
00287 this->set_clamped_to_screen(pFrame->is_clamped_to_screen());
00288 this->set_resizable(pFrame->is_resizable());
00289
00290 std::array<int,4> lAbsInsets = pFrame->get_abs_hit_rect_insets();
00291 this->set_abs_hit_rect_insets(lAbsInsets[0], lAbsInsets[1], lAbsInsets[2], lAbsInsets[3]);
00292 std::array<float,4> lRelInsets = pFrame->get_rel_hit_rect_insets();
00293 this->set_rel_hit_rect_insets(lRelInsets[0], lRelInsets[1], lRelInsets[2], lRelInsets[3]);
00294
00295 std::array<uint,2> lMax = pFrame->get_max_resize();
00296 this->set_max_resize(lMax[0], lMax[1]);
00297 std::array<uint,2> lMin = pFrame->get_min_resize();
00298 this->set_min_resize(lMin[0], lMin[1]);
00299
00300 this->set_scale(pFrame->get_scale());
00301
00302 std::map<uint, frame*>::const_iterator iterChild;
00303 foreach (iterChild, pFrame->lChildList_)
00304 {
00305 frame* pChild = iterChild->second;
00306 if (!pChild->is_special())
00307 {
00308 frame* pNewChild = pManager_->create_frame(pChild->get_object_type());
00309 if (pNewChild)
00310 {
00311 pNewChild->set_parent(this);
00312 if (this->is_virtual())
00313 pNewChild->set_virtual();
00314 pNewChild->set_name(pChild->get_raw_name());
00315 if (!pManager_->add_uiobject(pNewChild))
00316 {
00317 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00318 << "Trying to add \"" << pChild->get_name() << "\" to \"" << sName_
00319 << "\", but its name was already taken : \"" << pNewChild->get_name()
00320 << "\". Skipped." << std::endl;
00321
00322 delete pNewChild;
00323 continue;
00324 }
00325 pNewChild->create_glue();
00326 this->add_child(pNewChild);
00327 pNewChild->copy_from(pChild);
00328 pNewChild->notify_loaded();
00329 }
00330 }
00331 }
00332
00333 if (pFrame->pBackdrop_)
00334 {
00335 pBackdrop_ = utils::refptr<backdrop>(new backdrop(this));
00336 pBackdrop_->copy_from(*pFrame->pBackdrop_);
00337 }
00338
00339 if (pFrame->pTitleRegion_)
00340 {
00341 this->create_title_region();
00342 pTitleRegion_->copy_from(pFrame->pTitleRegion_);
00343 }
00344
00345 std::map<uint, layered_region*>::const_iterator iterRegion;
00346 foreach (iterRegion, pFrame->lRegionList_)
00347 {
00348 layered_region* pArt = iterRegion->second;
00349 if (!pArt->is_special())
00350 {
00351 layered_region* pNewArt = pManager_->create_layered_region(pArt->get_object_type());
00352 if (pNewArt)
00353 {
00354 pNewArt->set_parent(this);
00355 if (this->is_virtual())
00356 pNewArt->set_virtual();
00357 pNewArt->set_name(pArt->get_raw_name());
00358 if (!pManager_->add_uiobject(pNewArt))
00359 {
00360 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00361 << "Trying to add \"" << pArt->get_name() << "\" to \"" << sName_
00362 << "\", but its name was already taken : \"" << pNewArt->get_name()
00363 << "\". Skipped." << std::endl;
00364
00365 delete pNewArt;
00366 continue;
00367 }
00368 if (!pNewArt->is_virtual())
00369 pNewArt->create_glue();
00370
00371 pNewArt->set_draw_layer(pArt->get_draw_layer());
00372
00373 this->add_region(pNewArt);
00374 pNewArt->copy_from(pArt);
00375 pNewArt->notify_loaded();
00376 }
00377 }
00378 }
00379
00380 bBuildLayerList_ = true;
00381 }
00382 }
00383
00384 void frame::create_title_region()
00385 {
00386 if (!pTitleRegion_)
00387 {
00388 pTitleRegion_ = new region(pManager_);
00389 if (this->is_virtual())
00390 pTitleRegion_->set_virtual();
00391 pTitleRegion_->set_special();
00392 pTitleRegion_->set_parent(this);
00393 pTitleRegion_->set_name(sName_+"TitleRegion");
00394
00395 if (!pManager_->add_uiobject(pTitleRegion_))
00396 {
00397 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00398 << "Couldn't create \"" << sName_ << "\"'s title region because another uiobject "
00399 "already took its name : \"" << pTitleRegion_->get_name() << "\"." << std::endl;
00400
00401 delete pTitleRegion_; pTitleRegion_ = nullptr;
00402 return;
00403 }
00404
00405 if (!pTitleRegion_->is_virtual())
00406 pTitleRegion_->create_glue();
00407
00408 pTitleRegion_->notify_loaded();
00409 }
00410 else
00411 gui::out << gui::warning << "gui::" << lType_.back() << " : \""+sName_+"\" already has a title region." << std::endl;
00412 }
00413
00414 frame* frame::get_child(const std::string& sName) const
00415 {
00416 const uiobject* pObj = pManager_->get_uiobject_by_name(sName);
00417
00418 if (pObj)
00419 {
00420 std::map<uint, frame*>::const_iterator iter = lChildList_.find(pObj->get_id());
00421 if (iter != lChildList_.end())
00422 return iter->second;
00423 }
00424
00425 return nullptr;
00426 }
00427
00428 layered_region* frame::get_region(const std::string& sName) const
00429 {
00430 const uiobject* pObj = pManager_->get_uiobject_by_name(sName);
00431
00432 if (pObj)
00433 {
00434 std::map<uint, layered_region*>::const_iterator iter = lRegionList_.find(pObj->get_id());
00435 if (iter != lRegionList_.end())
00436 return lRegionList_.find(pObj->get_id())->second;
00437 }
00438
00439 return nullptr;
00440 }
00441
00442 void frame::set_abs_width(uint uiAbsWidth)
00443 {
00444 uiobject::set_abs_width(std::min(std::max(uiAbsWidth, uiMinWidth_), uiMaxWidth_));
00445 }
00446
00447 void frame::set_abs_height(uint uiAbsHeight)
00448 {
00449 uiobject::set_abs_height(std::min(std::max(uiAbsHeight, uiMinHeight_), uiMaxHeight_));
00450 }
00451
00452 void frame::check_position() const
00453 {
00454 if (lBorderList_[BORDER_RIGHT] - lBorderList_[BORDER_LEFT] < int(uiMinWidth_))
00455 {
00456 lBorderList_[BORDER_RIGHT] = lBorderList_[BORDER_LEFT] + uiMinWidth_;
00457 uiAbsWidth_ = uiMinWidth_;
00458 }
00459 else if (uint(lBorderList_[BORDER_RIGHT] - lBorderList_[BORDER_LEFT]) > uiMaxWidth_)
00460 {
00461 lBorderList_[BORDER_RIGHT] = lBorderList_[BORDER_LEFT] + uiMaxWidth_;
00462 uiAbsWidth_ = uiMaxWidth_;
00463 }
00464
00465 if (lBorderList_[BORDER_BOTTOM] - lBorderList_[BORDER_TOP] < int(uiMinHeight_))
00466 {
00467 lBorderList_[BORDER_BOTTOM] = lBorderList_[BORDER_TOP] + uiMinHeight_;
00468 uiAbsHeight_ = uiMinHeight_;
00469 }
00470 else if (uint(lBorderList_[BORDER_BOTTOM] - lBorderList_[BORDER_TOP]) > uiMaxHeight_)
00471 {
00472 lBorderList_[BORDER_BOTTOM] = lBorderList_[BORDER_TOP] + uiMaxHeight_;
00473 uiAbsHeight_ = uiMaxHeight_;
00474 }
00475
00476 if (bIsClampedToScreen_)
00477 {
00478 uint uiScreenW = pManager_->get_screen_width();
00479 uint uiScreenH = pManager_->get_screen_height();
00480
00481 if (lBorderList_[BORDER_RIGHT] > int(uiScreenW))
00482 {
00483 if (uint(lBorderList_[BORDER_RIGHT] - lBorderList_[BORDER_LEFT]) > uiScreenW)
00484 {
00485 lBorderList_[BORDER_LEFT] = 0;
00486 lBorderList_[BORDER_RIGHT] = uiScreenW;
00487 }
00488 else
00489 {
00490 lBorderList_[BORDER_RIGHT] = uiScreenW;
00491 lBorderList_[BORDER_LEFT] = uiScreenW - uiAbsWidth_;
00492 }
00493 }
00494 if (lBorderList_[BORDER_LEFT] < 0)
00495 {
00496 if (uint(lBorderList_[BORDER_RIGHT] - lBorderList_[BORDER_LEFT]) > uiScreenW)
00497 {
00498 lBorderList_[BORDER_LEFT] = 0;
00499 lBorderList_[BORDER_RIGHT] = uiScreenW;
00500 }
00501 else
00502 {
00503 lBorderList_[BORDER_LEFT] = 0;
00504 lBorderList_[BORDER_RIGHT] = uiAbsWidth_;
00505 }
00506 }
00507
00508 if (lBorderList_[BORDER_BOTTOM] > int(uiScreenH))
00509 {
00510 if (uint(lBorderList_[BORDER_BOTTOM] - lBorderList_[BORDER_TOP]) > uiScreenH)
00511 {
00512 lBorderList_[BORDER_TOP] = 0;
00513 lBorderList_[BORDER_BOTTOM] = uiScreenH;
00514 }
00515 else
00516 {
00517 lBorderList_[BORDER_BOTTOM] = uiScreenH;
00518 lBorderList_[BORDER_TOP] = uiScreenH - uiAbsHeight_;
00519 }
00520 }
00521 if (lBorderList_[BORDER_TOP] < 0)
00522 {
00523 if (uint(lBorderList_[BORDER_BOTTOM] - lBorderList_[BORDER_TOP]) > uiScreenH)
00524 {
00525 lBorderList_[BORDER_TOP] = 0;
00526 lBorderList_[BORDER_BOTTOM] = uiScreenH;
00527 }
00528 else
00529 {
00530 lBorderList_[BORDER_TOP] = 0;
00531 lBorderList_[BORDER_BOTTOM] = uiAbsHeight_;
00532 }
00533 }
00534 }
00535 }
00536
00537 void frame::disable_draw_layer(layer_type mLayerID)
00538 {
00539 layer& mLayer = lLayerList_[mLayerID];
00540 if (!mLayer.bDisabled)
00541 {
00542 mLayer.bDisabled = true;
00543 notify_renderer_need_redraw();
00544 }
00545 }
00546
00547 void frame::enable_draw_layer(layer_type mLayerID)
00548 {
00549 layer& mLayer = lLayerList_[mLayerID];
00550 if (!mLayer.bDisabled)
00551 {
00552 mLayer.bDisabled = false;
00553 notify_renderer_need_redraw();
00554 }
00555 }
00556
00557 void frame::enable_keyboard(bool bIsKeyboardEnabled)
00558 {
00559 if (!bVirtual_)
00560 {
00561 if (bIsKeyboardEnabled && !bIsKeyboardEnabled_)
00562 {
00563 event_receiver::register_event("KEY_PRESSED");
00564 event_receiver::register_event("KEY_RELEASED");
00565 }
00566 else if (!bIsKeyboardEnabled && bIsKeyboardEnabled_)
00567 {
00568 event_receiver::unregister_event("KEY_PRESSED");
00569 event_receiver::unregister_event("KEY_RELEASED");
00570 }
00571 }
00572
00573 bIsKeyboardEnabled_ = bIsKeyboardEnabled;
00574 }
00575
00576 void frame::enable_mouse(bool bIsMouseEnabled, bool bAllowWorldInput)
00577 {
00578 if (!bVirtual_)
00579 {
00580 if (bIsMouseEnabled && !bIsMouseEnabled_)
00581 {
00582 event_receiver::register_event("MOUSE_MOVED_RAW");
00583 event_receiver::register_event("MOUSE_PRESSED");
00584 event_receiver::register_event("MOUSE_DOUBLE_CLICKED");
00585 event_receiver::register_event("MOUSE_RELEASED");
00586 }
00587 else if (!bIsMouseEnabled && bIsMouseEnabled_)
00588 {
00589 event_receiver::unregister_event("MOUSE_MOVED_RAW");
00590 event_receiver::unregister_event("MOUSE_PRESSED");
00591 event_receiver::unregister_event("MOUSE_DOUBLE_CLICKED");
00592 event_receiver::unregister_event("MOUSE_RELEASED");
00593 }
00594 }
00595
00596 bAllowWorldInput_ = bAllowWorldInput;
00597 bIsMouseEnabled_ = bIsMouseEnabled;
00598 }
00599
00600 void frame::enable_mouse_wheel(bool bIsMouseWheelEnabled)
00601 {
00602 if (!bVirtual_)
00603 {
00604 if (bIsMouseWheelEnabled && !bIsMouseWheelEnabled_)
00605 event_receiver::register_event("MOUSE_WHEEL");
00606 else if (!bIsMouseWheelEnabled && bIsMouseWheelEnabled_)
00607 event_receiver::unregister_event("MOUSE_WHEEL");
00608 }
00609
00610 bIsMouseWheelEnabled_ = bIsMouseWheelEnabled;
00611 }
00612
00613 void frame::notify_loaded()
00614 {
00615 if (!bVirtual_)
00616 on("Load");
00617
00618 uiobject::notify_loaded();
00619 }
00620
00621 void frame::fire_build_layer_list()
00622 {
00623 bBuildLayerList_ = true;
00624 }
00625
00626 bool frame::has_script(const std::string& sScriptName) const
00627 {
00628 return lDefinedScriptList_.find(sScriptName) != lDefinedScriptList_.end() ||
00629 lDefinedHandlerList_.find(sScriptName) != lDefinedHandlerList_.end();
00630 }
00631
00632 void frame::add_region(layered_region* pRegion)
00633 {
00634 if (pRegion)
00635 {
00636 if (lRegionList_.find(pRegion->get_id()) == lRegionList_.end())
00637 {
00638 lRegionList_[pRegion->get_id()] = pRegion;
00639
00640 fire_build_layer_list();
00641 notify_renderer_need_redraw();
00642
00643 if (!bVirtual_)
00644 {
00645 utils::wptr<lua::state> pLua = pManager_->get_lua();
00646 const std::string& sRawName = pRegion->get_raw_name();
00647 if (utils::starts_with(sRawName, "$parent"))
00648 {
00649 std::string sTempName = pRegion->get_name();
00650 sTempName.erase(0, sName_.size());
00651 pLua->get_global(pRegion->get_name());
00652 pLua->set_global(sName_+"."+sTempName);
00653 }
00654 }
00655 }
00656 else
00657 {
00658 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00659 << "Trying to add \"" << pRegion->get_name() << "\" to \"" << sName_ << "\"'s children, "
00660 "but it was already one of this frame's children." << std::endl;
00661 }
00662 }
00663 }
00664
00665 void frame::remove_region(layered_region* pRegion)
00666 {
00667 if (pRegion)
00668 {
00669 std::map<uint, layered_region*>::iterator iter = lRegionList_.find(pRegion->get_id());
00670 if (iter != lRegionList_.end())
00671 {
00672 lRegionList_.erase(iter);
00673 fire_build_layer_list();
00674 notify_renderer_need_redraw();
00675 }
00676 else
00677 {
00678 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00679 << "Trying to remove \"" << pRegion->get_name() << "\" from \"" << sName_ << "\"'s children, "
00680 "but it was not one of this frame's children." << std::endl;
00681 }
00682 }
00683 }
00684
00685 layered_region* frame::create_region(layer_type mLayer, const std::string& sClassName, const std::string& sName, const std::string& sInheritance)
00686 {
00687 layered_region* pRegion = pManager_->create_layered_region(sClassName);
00688 pRegion->set_parent(this);
00689
00690 pRegion->set_draw_layer(mLayer);
00691 pRegion->set_name(sName);
00692
00693 if (pManager_->get_uiobject_by_name(pRegion->get_name()))
00694 {
00695 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00696 << "An object with the name " << pRegion->get_name() << " already exists." << std::endl;
00697
00698 delete pRegion;
00699 return nullptr;
00700 }
00701
00702 pManager_->add_uiobject(pRegion);
00703 pRegion->create_glue();
00704
00705 add_region(pRegion);
00706
00707 if (!utils::has_no_content(sInheritance))
00708 {
00709 std::vector<std::string> lObjects = utils::cut(sInheritance, ",");
00710 std::vector<std::string>::iterator iter;
00711 foreach (iter, lObjects)
00712 {
00713 utils::trim(*iter, ' ');
00714 uiobject* pObj = pManager_->get_uiobject_by_name(*iter, true);
00715 if (pObj)
00716 {
00717 if (pRegion->is_object_type(pObj->get_object_type()))
00718 {
00719
00720 pRegion->copy_from(pObj);
00721 }
00722 else
00723 {
00724 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00725 << "\"" << pRegion->get_name() << "\" (" << pRegion->get_object_type()
00726 << ") cannot inherit from \"" << *iter << "\" (" << pObj->get_object_type()
00727 << "). Inheritance skipped." << std::endl;
00728 }
00729 }
00730 else
00731 {
00732 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00733 << "Couldn't find inherited object \"" << *iter << "\". Inheritance skipped." << std::endl;
00734 }
00735 }
00736 }
00737
00738 return pRegion;
00739 }
00740
00741
00742 frame* frame::create_child(const std::string& sClassName, const std::string& sName, const std::string& sInheritance)
00743 {
00744 return pManager_->create_frame(sClassName, sName, this, sInheritance);
00745 }
00746
00747 void frame::add_child(frame* pChild)
00748 {
00749 if (pChild)
00750 {
00751 if (lChildList_.find(pChild->get_id()) == lChildList_.end())
00752 {
00753 if (bIsTopLevel_)
00754 pChild->notify_top_level_parent_(true, this);
00755
00756 if (pTopLevelParent_)
00757 pChild->notify_top_level_parent_(true, pTopLevelParent_);
00758
00759 if (is_visible() && pChild->is_shown())
00760 pChild->notify_visible_(!pManager_->is_loading_ui());
00761 else
00762 pChild->notify_invisible_(!pManager_->is_loading_ui());
00763
00764 pChild->set_manually_rendered(bManuallyRendered_, pRenderer_);
00765
00766 lChildList_[pChild->get_id()] = pChild;
00767
00768 notify_strata_changed_();
00769
00770 if (!bVirtual_)
00771 {
00772 utils::wptr<lua::state> pLua = pManager_->get_lua();
00773 std::string sRawName = pChild->get_raw_name();
00774 if (utils::starts_with(sRawName, "$parent"))
00775 {
00776 sRawName.erase(0, 7);
00777 pLua->get_global(pChild->get_lua_name());
00778 pLua->set_global(sLuaName_+"."+sRawName);
00779 }
00780 }
00781 }
00782 else
00783 {
00784 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00785 << "Trying to add \"" << pChild->get_name() << "\" to \"" << sName_
00786 << "\"'s children, but it was already one of this frame's children." << std::endl;
00787 }
00788 }
00789 }
00790
00791 void frame::remove_child(frame* pChild)
00792 {
00793 if (pChild)
00794 {
00795 std::map<uint, frame*>::iterator iter = lChildList_.find(pChild->get_id());
00796 if (iter != lChildList_.end())
00797 {
00798 lChildList_.erase(iter);
00799 notify_strata_changed_();
00800 }
00801 else
00802 {
00803 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00804 << "Trying to remove \"" << pChild->get_name() << "\" from \"" << sName_
00805 << "\"'s children, but it was not one of this frame's children." << std::endl;
00806 }
00807 }
00808 }
00809
00810 const std::map<uint, frame*>& frame::get_children() const
00811 {
00812 return lChildList_;
00813 }
00814
00815 float frame::get_effective_alpha() const
00816 {
00817 if (pParent_)
00818 return fAlpha_*pParentFrame_->get_effective_alpha();
00819 else
00820 return fAlpha_;
00821 }
00822
00823 float frame::get_effective_scale() const
00824 {
00825 if (pParent_)
00826 return fScale_*pParentFrame_->get_effective_scale();
00827 else
00828 return fScale_;
00829 }
00830
00831 int frame::get_frame_level() const
00832 {
00833 return iLevel_;
00834 }
00835
00836 frame_strata frame::get_frame_strata() const
00837 {
00838 return mStrata_;
00839 }
00840
00841 utils::wptr<backdrop> frame::get_backdrop() const
00842 {
00843 return pBackdrop_;
00844 }
00845
00846 const std::string& frame::get_frame_type() const
00847 {
00848 return lType_.back();
00849 }
00850
00851 const std::array<int,4>& frame::get_abs_hit_rect_insets() const
00852 {
00853 return lAbsHitRectInsetList_;
00854 }
00855
00856 const std::array<float,4>& frame::get_rel_hit_rect_insets() const
00857 {
00858 return lRelHitRectInsetList_;
00859 }
00860
00861 std::array<uint,2> frame::get_max_resize() const
00862 {
00863 return {{uiMaxWidth_, uiMaxHeight_}};
00864 }
00865
00866 std::array<uint,2> frame::get_min_resize() const
00867 {
00868 return {{uiMinWidth_, uiMinHeight_}};
00869 }
00870
00871 uint frame::get_num_children() const
00872 {
00873 return lChildList_.size();
00874 }
00875
00876 uint frame::get_num_regions() const
00877 {
00878 return lRegionList_.size();
00879 }
00880
00881 float frame::get_scale() const
00882 {
00883 return fScale_;
00884 }
00885
00886 region* frame::get_title_region() const
00887 {
00888 return pTitleRegion_;
00889 }
00890
00891 bool frame::is_clamped_to_screen() const
00892 {
00893 return bIsClampedToScreen_;
00894 }
00895
00896 bool frame::is_in_frame(int iX, int iY) const
00897 {
00898 bool bInFrame = (
00899 (lBorderList_[BORDER_LEFT] + lAbsHitRectInsetList_[BORDER_LEFT] <= iX &&
00900 iX <= lBorderList_[BORDER_RIGHT] - lAbsHitRectInsetList_[BORDER_RIGHT] - 1)
00901 &&
00902 (lBorderList_[BORDER_TOP] + lAbsHitRectInsetList_[BORDER_TOP] <= iY &&
00903 iY <= lBorderList_[BORDER_BOTTOM] - lAbsHitRectInsetList_[BORDER_BOTTOM] - 1)
00904 );
00905
00906 if (pTitleRegion_ && pTitleRegion_->is_in_region(iX, iY))
00907 return true;
00908 else
00909 return bInFrame;
00910 }
00911
00912 bool frame::is_keyboard_enabled() const
00913 {
00914 return bIsKeyboardEnabled_;
00915 }
00916
00917 bool frame::is_mouse_enabled() const
00918 {
00919 return bIsMouseEnabled_;
00920 }
00921
00922 bool frame::is_world_input_allowed() const
00923 {
00924 return bAllowWorldInput_;
00925 }
00926
00927 bool frame::is_mouse_wheel_enabled() const
00928 {
00929 return bIsMouseWheelEnabled_;
00930 }
00931
00932 bool frame::is_movable() const
00933 {
00934 return bIsMovable_;
00935 }
00936
00937 bool frame::is_resizable() const
00938 {
00939 return bIsResizable_;
00940 }
00941
00942 bool frame::is_top_level() const
00943 {
00944 return bIsTopLevel_;
00945 }
00946
00947 bool frame::is_user_placed() const
00948 {
00949 return bIsUserPlaced_;
00950 }
00951
00952 void frame::define_script(const std::string& sScriptName, const std::string& sContent, const std::string& sFile, uint uiLineNbr)
00953 {
00954 std::string sCutScriptName = sScriptName;
00955 sCutScriptName.erase(0, 2);
00956
00957 std::map<std::string, handler>::iterator iterH = lDefinedHandlerList_.find(sCutScriptName);
00958 if (iterH != lDefinedHandlerList_.end())
00959 lDefinedHandlerList_.erase(iterH);
00960
00961 std::string sAdjustedName = sScriptName;
00962 std::string::iterator iter;
00963 foreach (iter, sAdjustedName)
00964 {
00965 if ('A' <= *iter && *iter <= 'Z')
00966 {
00967 *iter = tolower(*iter);
00968 if (iter != sAdjustedName.begin())
00969 iter = sAdjustedName.insert(iter, '_');
00970 }
00971 }
00972
00973 std::string sStr;
00974 sStr += "function " + sLuaName_ + ":" + sAdjustedName + "() " + sContent + " end";
00975
00976
00977 utils::wptr<lua::state> pLua = pManager_->get_lua();
00978
00979 std::string sOldFile = pLua->get_global_string("_xml_file_name", false, "");
00980 uint uiOldLineNbr = pLua->get_global_int("_xml_line_nbr", false, 0);
00981 lua::c_function pErrorFunc = pLua->get_lua_error_function();
00982
00983 pLua->push_string(sFile); pLua->set_global("_xml_file_name");
00984 pLua->push_number(uiLineNbr); pLua->set_global("_xml_line_nbr");
00985 pLua->set_lua_error_function(l_xml_error);
00986
00987
00988 try
00989 {
00990 pLua->do_string(sStr);
00991 lDefinedScriptList_[sCutScriptName] = sContent;
00992 lXMLScriptInfoList_[sCutScriptName] = {sFile, uiLineNbr};
00993 }
00994 catch (lua::exception& e)
00995 {
00996 std::string sError = e.get_description();
00997
00998
00999
01000
01001
01002 if (sError[0] == '[')
01003 {
01004 size_t pos = sError.find("]");
01005 sError.erase(0, pos+2);
01006
01007 pos = sError.find(":");
01008 uint uiLuaLineNbr = utils::string_to_uint(sError.substr(0, pos));
01009
01010 sError.erase(0, pos+1);
01011
01012 sError = sFile + ":" + utils::to_string(uiLineNbr + uiLuaLineNbr - 1) + ":" + sError;
01013 }
01014
01015 gui::out << gui::error << sError << std::endl;
01016
01017 event mEvent("LUA_ERROR");
01018 mEvent.add(sError);
01019 pManager_->get_event_manager()->fire_event(mEvent);
01020 }
01021
01022 pLua->push_string(sOldFile); pLua->set_global("_xml_file_name");
01023 pLua->push_number(uiOldLineNbr); pLua->set_global("_xml_line_nbr");
01024 pLua->set_lua_error_function(pErrorFunc);
01025 }
01026
01027 void frame::define_script(const std::string& sScriptName, handler mHandler)
01028 {
01029 std::string sCutScriptName = sScriptName;
01030 sCutScriptName.erase(0, 2);
01031
01032 std::map<std::string, std::string>::iterator iter = lDefinedScriptList_.find(sCutScriptName);
01033 if (iter != lDefinedScriptList_.end())
01034 lDefinedScriptList_.erase(iter);
01035
01036 lDefinedHandlerList_[sCutScriptName] = mHandler;
01037 }
01038
01039 void frame::notify_script_defined(const std::string& sScriptName, bool bDefined)
01040 {
01041 std::string sCutScriptName = sScriptName;
01042 sCutScriptName.erase(0, 2);
01043
01044 std::map<std::string, script_info>::iterator iter = lXMLScriptInfoList_.find(sScriptName);
01045 if (iter != lXMLScriptInfoList_.end())
01046 lXMLScriptInfoList_.erase(iter);
01047
01048 if (bDefined)
01049 {
01050 std::map<std::string, handler>::iterator iter = lDefinedHandlerList_.find(sScriptName);
01051 if (iter != lDefinedHandlerList_.end())
01052 lDefinedHandlerList_.erase(iter);
01053
01054 lDefinedScriptList_[sCutScriptName] = "";
01055 } else
01056 lDefinedScriptList_.erase(sCutScriptName);
01057 }
01058
01059 void frame::on_event(const event& mEvent)
01060 {
01061 if (has_script("Event") &&
01062 (lRegEventList_.find(mEvent.get_name()) != lRegEventList_.end() || bHasAllEventsRegistred_))
01063 {
01064
01065 if (mEvent.get_name() == "ADDON_LOADED")
01066 {
01067 if (!pAddOn_ || pAddOn_->sName != mEvent.get(0)->get<std::string>())
01068 return;
01069 }
01070
01071 event mTemp = mEvent;
01072 on("Event", &mTemp);
01073 }
01074
01075 if (!pManager_->is_input_enabled())
01076 return;
01077
01078 if (bIsMouseEnabled_ && bIsVisible_)
01079 {
01080 if (mEvent.get_name() == "MOUSE_MOVED_RAW" ||
01081 mEvent.get_name() == "MOUSE_MOVED" ||
01082 mEvent.get_name() == "MOUSE_MOVED_SMOOTH")
01083 {
01084 if (!lMouseButtonList_.empty() && !bMouseDragged_)
01085 {
01086 std::vector<std::string>::iterator iterButton;
01087 foreach (iterButton, lMouseButtonList_)
01088 {
01089 if (lRegDragList_.find(*iterButton) != lRegDragList_.end())
01090 {
01091 on("DragStart");
01092 bMouseDragged_ = true;
01093 break;
01094 }
01095 }
01096 }
01097 }
01098 else if (mEvent.get_name() == "MOUSE_PRESSED")
01099 {
01100 if (bMouseInTitleRegion_)
01101 start_moving();
01102
01103 if (bMouseInFrame_)
01104 {
01105 if (bIsTopLevel_)
01106 raise();
01107
01108 if (pTopLevelParent_)
01109 pTopLevelParent_->raise();
01110
01111 std::string sMouseButton = mEvent[3].get<std::string>();
01112
01113 event mEvent2;
01114 mEvent2.add(sMouseButton);
01115
01116 on("MouseDown", &mEvent2);
01117 lMouseButtonList_.push_back(sMouseButton);
01118 }
01119 }
01120 else if (mEvent.get_name() == "MOUSE_RELEASED")
01121 {
01122 if (bIsMovable_)
01123 stop_moving();
01124
01125 std::string sMouseButton = mEvent[3].get<std::string>();
01126
01127 if (bMouseInFrame_)
01128 {
01129 event mEvent2;
01130 mEvent2.add(sMouseButton);
01131
01132 on("MouseUp", &mEvent2);
01133 }
01134
01135 std::vector<std::string>::iterator iter = utils::find(lMouseButtonList_, sMouseButton);
01136 if (iter != lMouseButtonList_.end())
01137 lMouseButtonList_.erase(iter);
01138
01139 if (bMouseDragged_)
01140 {
01141 bool bDrag = false;
01142 foreach (iter, lMouseButtonList_)
01143 {
01144 if (lRegDragList_.find(*iter) != lRegDragList_.end())
01145 {
01146 bDrag = true;
01147 break;
01148 }
01149 }
01150
01151 if (!bDrag)
01152 {
01153 on("DragStop");
01154 bMouseDragged_ = false;
01155 }
01156 }
01157 }
01158 else if (mEvent.get_name() == "MOUSE_WHEEL" || mEvent.get_name() == "MOUSE_WHEEL_SMOOTH")
01159 {
01160 if (bMouseInFrame_)
01161 {
01162 event mEvent2;
01163 mEvent2.add(mEvent[0].get<float>());
01164 on("MouseWheel", &mEvent2);
01165 }
01166 }
01167 }
01168
01169 if (bIsKeyboardEnabled_ && bIsVisible_)
01170 {
01171 if (mEvent.get_name() == "KEY_PRESSED")
01172 {
01173 event mKeyEvent;
01174 mKeyEvent.add(mEvent[0].get<uint>());
01175 mKeyEvent.add(mEvent[1].get<std::string>());
01176
01177 on("KeyDown", &mKeyEvent);
01178 }
01179 else if (mEvent.get_name() == "KEY_RELEASED")
01180 {
01181 event mKeyEvent;
01182 mKeyEvent.add(mEvent[0].get<uint>());
01183 mKeyEvent.add(mEvent[1].get<std::string>());
01184
01185 on("KeyUp", &mKeyEvent);
01186 }
01187 }
01188 }
01189
01190 int l_xml_error(lua_State* pLua)
01191 {
01192 if (!lua_isstring(pLua, -1))
01193 return 0;
01194
01195 lua_Debug d;
01196
01197 lua_getstack(pLua, 1, &d);
01198 lua_getinfo(pLua, "Sl", &d);
01199
01200 if (d.short_src[0] == '[')
01201 {
01202 lua_getglobal(pLua, "_xml_file_name");
01203 std::string sFile = lua_tostring(pLua, -1);
01204 lua_pop(pLua, 1);
01205 lua_getglobal(pLua, "_xml_line_nbr");
01206 uint uiLineNbr = lua_tonumber(pLua, -1);
01207 lua_pop(pLua, 1);
01208
01209 std::string sError = sFile + ":" + utils::to_string(uiLineNbr + d.currentline - 1) + ": "
01210 + std::string(lua_tostring(pLua, -1));
01211
01212 lua_pushstring(pLua, sError.c_str());
01213 }
01214 else
01215 {
01216 std::string sError = std::string(d.short_src) + ":" + utils::to_string(int(d.currentline)) + ": "
01217 + std::string(lua_tostring(pLua, -1));
01218
01219 lua_pushstring(pLua, sError.c_str());
01220 }
01221
01222 return 1;
01223 }
01224
01225 void frame::on(const std::string& sScriptName, event* pEvent)
01226 {
01227 std::map<std::string, handler>::const_iterator iterH = lDefinedHandlerList_.find(sScriptName);
01228 if (iterH != lDefinedHandlerList_.end())
01229 {
01230 if (iterH->second)
01231 iterH->second(this, pEvent);
01232 }
01233
01234 std::map<std::string, std::string>::const_iterator iter = lDefinedScriptList_.find(sScriptName);
01235 if (iter != lDefinedScriptList_.end())
01236 {
01237 utils::wptr<lua::state> pLua = pManager_->get_lua();
01238
01239 if ((sScriptName == "KeyDown") ||
01240 (sScriptName == "KeyUp"))
01241 {
01242
01243 if (pEvent)
01244 {
01245 pLua->push_number(pEvent->get(0)->get<uint>());
01246 pLua->set_global("arg1");
01247 pLua->push_string(pEvent->get(1)->get<std::string>());
01248 pLua->set_global("arg2");
01249 }
01250 }
01251 else if (sScriptName == "MouseDown")
01252 {
01253
01254 pLua->push_string(pEvent->get(0)->get<std::string>());
01255 pLua->set_global("arg1");
01256 }
01257 else if (sScriptName == "MouseUp")
01258 {
01259
01260 pLua->push_string(pEvent->get(0)->get<std::string>());
01261 pLua->set_global("arg1");
01262 }
01263 else if (sScriptName == "MouseWheel")
01264 {
01265 pLua->push_number(pEvent->get(0)->get<float>());
01266 pLua->set_global("arg1");
01267 }
01268 else if (sScriptName == "Update")
01269 {
01270
01271 pLua->push_number(pEvent->get(0)->get<float>());
01272 pLua->set_global("arg1");
01273 }
01274 else if (sScriptName == "Event")
01275 {
01276
01277 pLua->push_string(pEvent->get_name());
01278 pLua->set_global("event");
01279
01280
01281 for (uint i = 0; i < pEvent->get_num_param(); ++i)
01282 {
01283 const lua::var* pArg = pEvent->get(i);
01284 pLua->push(*pArg);
01285 pLua->set_global("arg"+utils::to_string(i+1));
01286 }
01287 }
01288
01289 std::string sAdjustedName = sScriptName;
01290 std::string::iterator iterStr;
01291 foreach (iterStr, sAdjustedName)
01292 {
01293 if ('A' <= *iterStr && *iterStr <= 'Z')
01294 {
01295 *iterStr = tolower(*iterStr);
01296 iterStr = sAdjustedName.insert(iterStr, '_');
01297 }
01298 }
01299
01300 lua::c_function pErrorFunc = nullptr;
01301 std::string sFile = "";
01302 uint uiLineNbr = 0;
01303
01304 if (!iter->second.empty())
01305 {
01306
01307
01308 pErrorFunc = pLua->get_lua_error_function();
01309
01310 std::map<std::string, script_info>::const_iterator iter = lXMLScriptInfoList_.find(sScriptName);
01311 if (iter != lXMLScriptInfoList_.end())
01312 {
01313 sFile = pLua->get_global_string("_xml_file_name", false, "");
01314 uiLineNbr = pLua->get_global_int("_xml_line_nbr", false, 0);
01315
01316 pLua->push_string(iter->second.sFile); pLua->set_global("_xml_file_name");
01317 pLua->push_number(iter->second.uiLineNbr); pLua->set_global("_xml_line_nbr");
01318
01319 pLua->set_lua_error_function(l_xml_error);
01320 }
01321 }
01322
01323 pManager_->set_current_addon(pAddOn_);
01324
01325 try { pLua->call_function(sName_+":on"+sAdjustedName); }
01326 catch (lua::exception& e)
01327 {
01328 std::string sError = e.get_description();
01329
01330 gui::out << gui::error << sError << std::endl;
01331
01332 event mEvent("LUA_ERROR");
01333 mEvent.add(sError);
01334 pManager_->get_event_manager()->fire_event(mEvent);
01335 }
01336
01337 if (!iter->second.empty())
01338 {
01339 pLua->push_string(sFile); pLua->set_global("_xml_file_name");
01340 pLua->push_number(uiLineNbr); pLua->set_global("_xml_line_nbr");
01341
01342 pLua->set_lua_error_function(pErrorFunc);
01343 }
01344 }
01345 }
01346
01347 void frame::register_all_events()
01348 {
01349 bHasAllEventsRegistred_ = true;
01350 lRegEventList_.clear();
01351 }
01352
01353 void frame::register_event(const std::string& sEvent)
01354 {
01355 lRegEventList_.insert(sEvent);
01356 event_receiver::register_event(sEvent);
01357 }
01358
01359 void frame::register_for_drag(const std::vector<std::string>& lButtonList)
01360 {
01361 lRegDragList_.clear();
01362 std::vector<std::string>::const_iterator iterButton;
01363 foreach (iterButton, lButtonList)
01364 lRegDragList_.insert(*iterButton);
01365 }
01366
01367 void frame::set_clamped_to_screen(bool bIsClampedToScreen)
01368 {
01369 bIsClampedToScreen_ = bIsClampedToScreen;
01370 }
01371
01372 void frame::set_frame_strata(frame_strata mStrata)
01373 {
01374 if (mStrata == STRATA_PARENT)
01375 {
01376 if (!bVirtual_)
01377 {
01378 if (pParentFrame_)
01379 mStrata = pParentFrame_->get_frame_strata();
01380 else
01381 mStrata = STRATA_MEDIUM;
01382 }
01383 }
01384
01385 if (mStrata_ != mStrata && !bVirtual_)
01386 notify_strata_changed_();
01387
01388 mStrata_ = mStrata;
01389 }
01390
01391 void frame::set_frame_strata(const std::string& sStrata)
01392 {
01393 frame_strata mStrata;
01394
01395 if (sStrata == "BACKGROUND")
01396 mStrata = STRATA_BACKGROUND;
01397 else if (sStrata == "LOW")
01398 mStrata = STRATA_LOW;
01399 else if (sStrata == "MEDIUM")
01400 mStrata = STRATA_MEDIUM;
01401 else if (sStrata == "HIGH")
01402 mStrata = STRATA_HIGH;
01403 else if (sStrata == "DIALOG")
01404 mStrata = STRATA_DIALOG;
01405 else if (sStrata == "FULLSCREEN")
01406 mStrata = STRATA_FULLSCREEN;
01407 else if (sStrata == "FULLSCREEN_DIALOG")
01408 mStrata = STRATA_FULLSCREEN_DIALOG;
01409 else if (sStrata == "TOOLTIP")
01410 mStrata = STRATA_TOOLTIP;
01411 else if (sStrata == "PARENT")
01412 {
01413 if (bVirtual_)
01414 mStrata = STRATA_PARENT;
01415 else
01416 {
01417 if (pParentFrame_)
01418 mStrata = pParentFrame_->get_frame_strata();
01419 else
01420 mStrata = STRATA_MEDIUM;
01421 }
01422 }
01423 else
01424 {
01425 gui::out << gui::warning << "gui::" << lType_.back() << " : Unknown strata : \""+sStrata+"\"." << std::endl;
01426 return;
01427 }
01428
01429 set_frame_strata(mStrata);
01430 }
01431
01432 void frame::set_backdrop(utils::refptr<backdrop> pBackdrop)
01433 {
01434 pBackdrop_ = pBackdrop;
01435 notify_renderer_need_redraw();
01436 }
01437
01438 void frame::set_abs_hit_rect_insets(int iLeft, int iRight, int iTop, int iBottom)
01439 {
01440 lAbsHitRectInsetList_ = {{iLeft, iRight, iTop, iBottom}};
01441 }
01442
01443 void frame::set_rel_hit_rect_insets(float fLeft, float fRight, float fTop, float fBottom)
01444 {
01445 lRelHitRectInsetList_ = {{fLeft, fRight, fTop, fBottom}};
01446 }
01447
01448 void frame::set_level(int iLevel)
01449 {
01450 if (iLevel != iLevel_)
01451 {
01452 iLevel_ = iLevel;
01453
01454 if (!bVirtual_)
01455 notify_strata_changed_();
01456 }
01457 }
01458
01459 void frame::set_max_resize(uint uiMaxWidth, uint uiMaxHeight)
01460 {
01461 set_max_height(uiMaxHeight);
01462 set_max_width(uiMaxWidth);
01463 }
01464
01465 void frame::set_min_resize(uint uiMinWidth, uint uiMinHeight)
01466 {
01467 set_min_height(uiMinHeight);
01468 set_min_width(uiMinWidth);
01469 }
01470
01471 void frame::set_max_height(uint uiMaxHeight)
01472 {
01473 if (uiMaxHeight >= uiMinHeight_)
01474 uiMaxHeight_ = uiMaxHeight;
01475
01476 if (uiMaxHeight_ != uiMaxHeight)
01477 fire_update_dimensions();
01478 }
01479
01480 void frame::set_max_width(uint uiMaxWidth)
01481 {
01482 if (uiMaxWidth >= uiMinWidth_)
01483 uiMaxWidth_ = uiMaxWidth;
01484
01485 if (uiMaxWidth_ != uiMaxWidth)
01486 fire_update_dimensions();
01487 }
01488
01489 void frame::set_min_height(uint uiMinHeight)
01490 {
01491 if (uiMinHeight <= uiMaxHeight_)
01492 uiMinHeight_ = uiMinHeight;
01493
01494 if (uiMinHeight_ != uiMinHeight)
01495 fire_update_dimensions();
01496 }
01497
01498 void frame::set_min_width(uint uiMinWidth)
01499 {
01500 if (uiMinWidth <= uiMaxWidth_)
01501 uiMinWidth_ = uiMinWidth;
01502
01503 if (uiMinWidth_ != uiMinWidth)
01504 fire_update_dimensions();
01505 }
01506
01507 void frame::set_movable(bool bIsMovable)
01508 {
01509 bIsMovable_ = bIsMovable;
01510 }
01511
01512 void frame::set_parent(uiobject* pParent)
01513 {
01514 if (pParent != this)
01515 {
01516 if (!pParentFrame_ && uiID_ != uint(-1))
01517 pManager_->notify_object_has_parent(this);
01518
01519 pParent_ = pParent;
01520 pParentFrame_ = dynamic_cast<frame*>(pParent);
01521
01522 if (!pAddOn_ && pParentFrame_)
01523 pAddOn_ = pParentFrame_->get_addon();
01524
01525 fire_update_dimensions();
01526 }
01527 else
01528 gui::out << gui::error << "gui::" << lType_.back() << " : Can't call set_parent(this)." << std::endl;
01529 }
01530
01531 void frame::set_resizable(bool bIsResizable)
01532 {
01533 bIsResizable_ = bIsResizable;
01534 }
01535
01536 void frame::set_scale(float fScale)
01537 {
01538 fScale_ = fScale;
01539 if (fScale_ != fScale)
01540 notify_renderer_need_redraw();
01541 }
01542
01543 void frame::set_top_level(bool bIsTopLevel)
01544 {
01545 if (bIsTopLevel_ != bIsTopLevel)
01546 {
01547 bIsTopLevel_ = bIsTopLevel;
01548
01549 std::map<uint, frame*>::iterator iterChild;
01550 foreach (iterChild, lChildList_)
01551 iterChild->second->notify_top_level_parent_(bIsTopLevel_, this);
01552 }
01553 }
01554
01555 void frame::raise()
01556 {
01557 if (bIsTopLevel_)
01558 {
01559 int iOldLevel = iLevel_;
01560 iLevel_ = pManager_->get_highest_level(mStrata_) + 1;
01561
01562 if (iLevel_ > iOldLevel)
01563 {
01564 int iAmount = iLevel_ - iOldLevel;
01565
01566 std::map<uint, frame*>::iterator iterChild;
01567 foreach (iterChild, lChildList_)
01568 iterChild->second->add_level_(iAmount);
01569
01570 notify_strata_changed_();
01571 }
01572 else
01573 iLevel_ = iOldLevel;
01574 }
01575 }
01576
01577 void frame::add_level_(int iAmount)
01578 {
01579 iLevel_ += iAmount;
01580
01581 std::map<uint, frame*>::iterator iterChild;
01582 foreach (iterChild, lChildList_)
01583 iterChild->second->add_level_(iAmount);
01584
01585 notify_strata_changed_();
01586 }
01587
01588 void frame::set_user_placed(bool bIsUserPlaced)
01589 {
01590 bIsUserPlaced_ = bIsUserPlaced;
01591 }
01592
01593 void frame::start_moving()
01594 {
01595 if (bIsMovable_)
01596 pManager_->start_moving(this);
01597 }
01598
01599 void frame::stop_moving()
01600 {
01601 pManager_->stop_moving(this);
01602 }
01603
01604 void frame::start_sizing(const anchor_point& mPoint)
01605 {
01606 if (bIsResizable_)
01607 pManager_->start_sizing(this, mPoint);
01608 }
01609
01610 void frame::stop_sizing()
01611 {
01612 pManager_->stop_sizing(this);
01613 }
01614
01615 void frame::set_manually_rendered(bool bManuallyRendered, uiobject* pRenderer)
01616 {
01617 if (bManuallyRendered_ != bManuallyRendered)
01618 notify_strata_changed_();
01619
01620 uiobject::set_manually_rendered(bManuallyRendered, pRenderer);
01621
01622 std::map<uint, frame*>::iterator iterChild;
01623 foreach (iterChild, lChildList_)
01624 iterChild->second->set_manually_rendered(bManuallyRendered, pRenderer);
01625 }
01626
01627 void frame::notify_child_strata_changed(frame* pChild)
01628 {
01629 if (pParentFrame_)
01630 pParentFrame_->notify_child_strata_changed(this);
01631 else
01632 pManager_->fire_build_strata_list();
01633 }
01634
01635 void frame::notify_strata_changed_()
01636 {
01637 if (pParentFrame_)
01638 pParentFrame_->notify_child_strata_changed(this);
01639 else
01640 pManager_->fire_build_strata_list();
01641 }
01642
01643 void frame::notify_visible_(bool bTriggerEvents)
01644 {
01645 bIsVisible_ = true;
01646 std::map<uint, frame*>::iterator iterChild;
01647 foreach (iterChild, lChildList_)
01648 {
01649 if (iterChild->second->is_shown())
01650 iterChild->second->notify_visible_(bTriggerEvents);
01651 }
01652
01653 if (bTriggerEvents)
01654 {
01655 lQueuedEventList_.push_back("Show");
01656 notify_renderer_need_redraw();
01657 }
01658 }
01659
01660 void frame::notify_invisible_(bool bTriggerEvents)
01661 {
01662 bIsVisible_ = false;
01663 std::map<uint, frame*>::iterator iterChild;
01664 foreach (iterChild, lChildList_)
01665 {
01666 if (iterChild->second->is_shown())
01667 iterChild->second->notify_invisible_(bTriggerEvents);
01668 }
01669
01670 if (bTriggerEvents)
01671 {
01672 lQueuedEventList_.push_back("Hide");
01673 notify_renderer_need_redraw();
01674 }
01675 }
01676
01677 void frame::notify_top_level_parent_(bool bTopLevel, frame* pParent)
01678 {
01679 if (bTopLevel)
01680 pTopLevelParent_ = pParent;
01681 else
01682 pTopLevelParent_ = nullptr;
01683
01684 std::map<uint, frame*>::iterator iterChild;
01685 foreach (iterChild, lChildList_)
01686 iterChild->second->notify_top_level_parent_(bTopLevel, pParent);
01687 }
01688
01689 void frame::notify_renderer_need_redraw() const
01690 {
01691 if (!bVirtual_)
01692 {
01693 if (pRenderer_)
01694 pRenderer_->fire_redraw();
01695 else
01696 pManager_->fire_redraw(mStrata_);
01697 }
01698 }
01699
01700 void frame::show()
01701 {
01702 if (!bIsShown_)
01703 {
01704 uiobject::show();
01705
01706 if (!pParent_ || pParent_->is_visible())
01707 notify_visible_();
01708 }
01709 }
01710
01711 void frame::hide()
01712 {
01713 if (bIsShown_)
01714 {
01715 uiobject::hide();
01716
01717 if (bIsVisible_)
01718 notify_invisible_();
01719 }
01720 }
01721
01722 void frame::set_shown(bool bIsShown)
01723 {
01724 if (bIsShown_ != bIsShown)
01725 {
01726 bIsShown_ = bIsShown;
01727
01728 if (!bIsShown_)
01729 notify_invisible_(false);
01730 }
01731 }
01732
01733 void frame::unregister_all_events()
01734 {
01735 bHasAllEventsRegistred_ = false;
01736 lRegEventList_.clear();
01737 }
01738
01739 void frame::unregister_event(const std::string& sEvent)
01740 {
01741 lRegEventList_.erase(sEvent);
01742 }
01743
01744 void frame::set_addon(addon* pAddOn)
01745 {
01746 if (!pAddOn_)
01747 pAddOn_ = pAddOn;
01748 else
01749 gui::out << gui::warning << "gui::" << lType_.back() << " : set_addon() can only be called once." << std::endl;
01750 }
01751
01752 addon* frame::get_addon() const
01753 {
01754 return pAddOn_;
01755 }
01756
01757 void frame::notify_mouse_in_frame(bool bMouseInframe, int iX, int iY)
01758 {
01759 if (bMouseInframe)
01760 {
01761 if (!bMouseInFrame_)
01762 on("Enter");
01763
01764 bMouseInFrame_ = true;
01765
01766 iMousePosX_ = iX;
01767 iMousePosY_ = iY;
01768
01769 bMouseInTitleRegion_ = (pTitleRegion_ && pTitleRegion_->is_in_region(iX, iY));
01770 }
01771 else
01772 {
01773 if (bMouseInFrame_)
01774 on("Leave");
01775
01776 bMouseInTitleRegion_ = false;
01777 bMouseInFrame_ = false;
01778 }
01779 }
01780
01781 void frame::update_borders_() const
01782 {
01783 bool bPositionUpdated = bUpdateBorders_;
01784 uiobject::update_borders_();
01785
01786 if (bPositionUpdated)
01787 check_position();
01788 }
01789
01790 void frame::update(float fDelta)
01791 {
01792
01793 #define DEBUG_LOG(msg)
01794
01795 uint uiOldWidth = uiAbsWidth_;
01796 uint uiOldHeight = uiAbsHeight_;
01797
01798 DEBUG_LOG(" ~");
01799 uiobject::update(fDelta);
01800 DEBUG_LOG(" #");
01801
01802 std::vector<std::string>::iterator iterEvent;
01803 foreach (iterEvent, lQueuedEventList_)
01804 {
01805 DEBUG_LOG(" Event " + *iterEvent);
01806 on(*iterEvent);
01807 }
01808
01809 lQueuedEventList_.clear();
01810
01811 if (bBuildLayerList_)
01812 {
01813 DEBUG_LOG(" Build layers");
01814
01815 std::map<layer_type, layer >::iterator iterLayer;
01816 foreach (iterLayer, lLayerList_)
01817 iterLayer->second.lRegionList.clear();
01818
01819
01820 std::map<uint, layered_region*>::iterator iterRegion;
01821 foreach (iterRegion, lRegionList_)
01822 {
01823 layered_region* pRegion = iterRegion->second;
01824 if (pRegion->get_object_type() != "font_string")
01825 lLayerList_[pRegion->get_draw_layer()].lRegionList.push_back(pRegion);
01826 }
01827
01828 foreach (iterRegion, lRegionList_)
01829 {
01830 layered_region* pRegion = iterRegion->second;
01831 if (pRegion->get_object_type() == "font_string")
01832 lLayerList_[pRegion->get_draw_layer()].lRegionList.push_back(pRegion);
01833 }
01834
01835 bBuildLayerList_ = false;
01836 }
01837
01838 if (is_visible())
01839 {
01840 DEBUG_LOG(" On update");
01841 event mEvent;
01842 mEvent.add(fDelta);
01843 on("Update", &mEvent);
01844 }
01845
01846 if (pTitleRegion_)
01847 pTitleRegion_->update(fDelta);
01848
01849
01850 DEBUG_LOG(" Update regions");
01851 std::map<uint, layered_region*>::iterator iterRegion;
01852 foreach (iterRegion, lRegionList_)
01853 iterRegion->second->update(fDelta);
01854
01855
01856 DEBUG_LOG(" Update children");
01857 std::map<uint, frame*>::iterator iterChild;
01858 foreach (iterChild, lChildList_)
01859 iterChild->second->update(fDelta);
01860
01861 if (uiOldWidth != uiAbsWidth_ || uiOldHeight != uiAbsHeight_)
01862 {
01863 DEBUG_LOG(" On size changed");
01864 on("SizeChanged");
01865 }
01866
01867 DEBUG_LOG(" .");
01868 }
01869
01870 std::vector<uiobject*> frame::clear_links()
01871 {
01872 std::vector<uiobject*> lList = uiobject::clear_links();
01873
01874 std::map<uint, layered_region*> lTempRegionList = lRegionList_;
01875 std::map<uint, layered_region*>::iterator iterRegion;
01876 foreach (iterRegion, lTempRegionList)
01877 {
01878 std::vector<uiobject*> lTempList = iterRegion->second->clear_links();
01879 for (auto iter : lTempList)
01880 lList.push_back(iter);
01881 }
01882
01883 std::map<uint, frame*> lTempChildList = lChildList_;
01884 std::map<uint, frame*>::iterator iterChild;
01885 foreach (iterChild, lTempChildList)
01886 {
01887 std::vector<uiobject*> lTempList = iterChild->second->clear_links();
01888 for (auto iter : lTempList)
01889 lList.push_back(iter);
01890 }
01891
01892 return lList;
01893 }
01894
01895 layer_type layer::get_layer_type(const std::string& sLayer)
01896 {
01897 if (sLayer == "ARTWORK")
01898 return LAYER_ARTWORK;
01899 else if (sLayer == "BACKGROUND")
01900 return LAYER_BACKGROUND;
01901 else if (sLayer == "BORDER")
01902 return LAYER_BORDER;
01903 else if (sLayer == "HIGHLIGHT")
01904 return LAYER_HIGHLIGHT;
01905 else if (sLayer == "OVERLAY")
01906 return LAYER_OVERLAY;
01907 else
01908 {
01909 gui::out << gui::warning << "layer : Uknown layer type : \""
01910 << sLayer << "\". Using \"ARTWORK\"." << std::endl;
01911
01912 return LAYER_ARTWORK;
01913 }
01914 }
01915 }