MyGUI  3.2.0
MyGUI_Widget.cpp
Go to the documentation of this file.
00001 
00006 /*
00007     This file is part of MyGUI.
00008 
00009     MyGUI is free software: you can redistribute it and/or modify
00010     it under the terms of the GNU Lesser General Public License as published by
00011     the Free Software Foundation, either version 3 of the License, or
00012     (at your option) any later version.
00013 
00014     MyGUI is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00021 */
00022 #include "MyGUI_Precompiled.h"
00023 #include "MyGUI_Widget.h"
00024 #include "MyGUI_Gui.h"
00025 #include "MyGUI_InputManager.h"
00026 #include "MyGUI_SkinManager.h"
00027 #include "MyGUI_SubWidgetManager.h"
00028 #include "MyGUI_WidgetManager.h"
00029 #include "MyGUI_ResourceSkin.h"
00030 #include "MyGUI_WidgetDefines.h"
00031 #include "MyGUI_LayerItem.h"
00032 #include "MyGUI_LayerManager.h"
00033 #include "MyGUI_RenderItem.h"
00034 #include "MyGUI_ISubWidget.h"
00035 #include "MyGUI_ISubWidgetText.h"
00036 #include "MyGUI_TextBox.h"
00037 #include "MyGUI_FactoryManager.h"
00038 #include "MyGUI_CoordConverter.h"
00039 #include "MyGUI_RenderManager.h"
00040 #include "MyGUI_ToolTipManager.h"
00041 #include "MyGUI_LayoutManager.h"
00042 
00043 namespace MyGUI
00044 {
00045 
00046     Widget::Widget() :
00047         mWidgetClient(nullptr),
00048         mEnabled(true),
00049         mInheritsEnabled(true),
00050         mInheritsVisible(true),
00051         mAlpha(ALPHA_MAX),
00052         mRealAlpha(ALPHA_MAX),
00053         mInheritsAlpha(true),
00054         mParent(nullptr),
00055         mWidgetStyle(WidgetStyle::Child),
00056         mContainer(nullptr),
00057         mAlign(Align::Default),
00058         mVisible(true)
00059     {
00060     }
00061 
00062     Widget::~Widget()
00063     {
00064     }
00065 
00066     void Widget::_initialise(WidgetStyle _style, const IntCoord& _coord, const std::string& _skinName, Widget* _parent, ICroppedRectangle* _croppedParent, const std::string& _name)
00067     {
00068         ResourceSkin* skinInfo = nullptr;
00069         ResourceLayout* templateInfo = nullptr;
00070 
00071         if (LayoutManager::getInstance().isExist(_skinName))
00072             templateInfo = LayoutManager::getInstance().getByName(_skinName);
00073         else
00074             skinInfo = SkinManager::getInstance().getByName(_skinName);
00075 
00076         mCoord = _coord;
00077 
00078         mAlign = Align::Default;
00079         mWidgetStyle = _style;
00080         mName = _name;
00081 
00082         mCroppedParent = _croppedParent;
00083         mParent = _parent;
00084 
00085 
00086 #if MYGUI_DEBUG_MODE == 1
00087         // проверяем соответсвие входных данных
00088         if (mWidgetStyle == WidgetStyle::Child)
00089         {
00090             MYGUI_ASSERT(mCroppedParent, "must be cropped");
00091             MYGUI_ASSERT(mParent, "must be parent");
00092         }
00093         else if (mWidgetStyle == WidgetStyle::Overlapped)
00094         {
00095             MYGUI_ASSERT((mParent == nullptr) == (mCroppedParent == nullptr), "error cropped");
00096         }
00097         else if (mWidgetStyle == WidgetStyle::Popup)
00098         {
00099             MYGUI_ASSERT(!mCroppedParent, "cropped must be nullptr");
00100             MYGUI_ASSERT(mParent, "must be parent");
00101         }
00102 #endif
00103 
00104         // корректируем абсолютные координаты
00105         mAbsolutePosition = _coord.point();
00106 
00107         if (nullptr != mCroppedParent)
00108             mAbsolutePosition += mCroppedParent->getAbsolutePosition();
00109 
00110         const WidgetInfo* root = initialiseWidgetSkinBase(skinInfo, templateInfo);
00111 
00112         // дочернее окно обыкновенное
00113         if (mWidgetStyle == WidgetStyle::Child)
00114         {
00115             if (mParent)
00116                 mParent->addChildItem(this);
00117         }
00118         // дочернее нуно перекрывающееся
00119         else if (mWidgetStyle == WidgetStyle::Overlapped)
00120         {
00121             // дочернее перекрывающееся
00122             if (mParent)
00123                 mParent->addChildNode(this);
00124         }
00125 
00126         // витр метод для наследников
00127         initialiseOverride();
00128 
00129         if (skinInfo != nullptr)
00130             setSkinProperty(skinInfo);
00131 
00132         if (root != nullptr)
00133         {
00134             for (VectorStringPairs::const_iterator iter = root->properties.begin(); iter != root->properties.end(); ++iter)
00135             {
00136                 setProperty(iter->first, iter->second);
00137             }
00138         }
00139     }
00140 
00141     void Widget::_shutdown()
00142     {
00143         // витр метод для наследников
00144         shutdownOverride();
00145 
00146         shutdownWidgetSkinBase();
00147 
00148         _destroyAllChildWidget();
00149 
00150         // дочернее окно обыкновенное
00151         if (mWidgetStyle == WidgetStyle::Child)
00152         {
00153             if (mParent)
00154                 mParent->removeChildItem(this);
00155         }
00156         // дочернее нуно перекрывающееся
00157         else if (mWidgetStyle == WidgetStyle::Overlapped)
00158         {
00159             // дочернее перекрывающееся
00160             if (mParent)
00161                 mParent->removeChildNode(this);
00162         }
00163 
00164         mParent = nullptr;
00165         mCroppedParent = nullptr;
00166     }
00167 
00168     void Widget::changeWidgetSkin(const std::string& _skinName)
00169     {
00170         ResourceSkin* skinInfo = nullptr;
00171         ResourceLayout* templateInfo = nullptr;
00172 
00173         if (LayoutManager::getInstance().isExist(_skinName))
00174             templateInfo = LayoutManager::getInstance().getByName(_skinName);
00175         else
00176             skinInfo = SkinManager::getInstance().getByName(_skinName);
00177 
00178         shutdownOverride();
00179 
00180         saveLayerItem();
00181 
00182         shutdownWidgetSkinBase();
00183         const WidgetInfo* root = initialiseWidgetSkinBase(skinInfo, templateInfo);
00184 
00185         restoreLayerItem();
00186 
00187         initialiseOverride();
00188 
00189         if (skinInfo != nullptr)
00190             setSkinProperty(skinInfo);
00191 
00192         if (root != nullptr)
00193         {
00194             for (VectorStringPairs::const_iterator iter = root->properties.begin(); iter != root->properties.end(); ++iter)
00195             {
00196                 setProperty(iter->first, iter->second);
00197             }
00198         }
00199     }
00200 
00201     const WidgetInfo* Widget::initialiseWidgetSkinBase(ResourceSkin* _skinInfo, ResourceLayout* _templateInfo)
00202     {
00203         const WidgetInfo* root  = nullptr;
00204         bool skinOnly = false;
00205 
00206         if (_skinInfo == nullptr)
00207         {
00208             skinOnly = true;
00209             std::string skinName;
00210 
00211             const VectorWidgetInfo& data = _templateInfo->getLayoutData();
00212             for (VectorWidgetInfo::const_iterator item = data.begin(); item != data.end(); ++item)
00213             {
00214                 if ((*item).name == "Root")
00215                 {
00216                     skinName = (*item).skin;
00217                     root = &(*item);
00218                     break;
00219                 }
00220             }
00221 
00222             _skinInfo = SkinManager::getInstance().getByName(skinName);
00223         }
00224 
00225         //SAVE
00226         const IntSize& _size = mCoord.size();
00227 
00228         if (_skinInfo != nullptr)
00229         {
00230             //FIXME - явный вызов
00231             Widget::setSize(_skinInfo->getSize());
00232 
00233             _createSkinItem(_skinInfo);
00234         }
00235 
00236         // выставляем альфу, корректировка по отцу автоматически
00237         _updateAlpha();
00238         _updateEnabled();
00239         _updateVisible();
00240 
00241         if (!skinOnly)
00242         {
00243             const MapString& properties = _skinInfo->getProperties();
00244             for (MapString::const_iterator item = properties.begin(); item != properties.end(); ++item)
00245             {
00246                 if (BackwardCompatibility::isIgnoreProperty((*item).first))
00247                     setUserString((*item).first, (*item).second);
00248             }
00249 
00250             // создаем детей скина
00251             const VectorChildSkinInfo& child = _skinInfo->getChild();
00252             for (VectorChildSkinInfo::const_iterator iter = child.begin(); iter != child.end(); ++iter)
00253             {
00254                 Widget* widget = baseCreateWidget(iter->style, iter->type, iter->skin, iter->coord, iter->align, iter->layer, iter->name, true);
00255                 // заполняем UserString пропертями
00256                 for (MapString::const_iterator prop = iter->params.begin(); prop != iter->params.end(); ++prop)
00257                     widget->setUserString(prop->first, prop->second);
00258             }
00259         }
00260 
00261         if (root != nullptr)
00262         {
00263             //FIXME - явный вызов
00264             Widget::setSize(root->intCoord.size());
00265 
00266             for (MapString::const_iterator iter = root->userStrings.begin(); iter != root->userStrings.end(); ++iter)
00267             {
00268                 setUserString(iter->first, iter->second);
00269             }
00270 
00271             for (VectorWidgetInfo::const_iterator iter = root->childWidgetsInfo.begin(); iter != root->childWidgetsInfo.end(); ++iter)
00272             {
00273                 _templateInfo->createWidget(*iter, "", this, true);
00274             }
00275         }
00276 
00277         //FIXME - явный вызов
00278         Widget::setSize(_size);
00279 
00280         return root;
00281     }
00282 
00283     void Widget::shutdownWidgetSkinBase()
00284     {
00285         setMaskPick("");
00286 
00287         _deleteSkinItem();
00288 
00289         // удаляем виджеты чтобы ли в скине
00290         for (VectorWidgetPtr::iterator iter = mWidgetChildSkin.begin(); iter != mWidgetChildSkin.end(); ++iter)
00291         {
00292             // Добавляем себя чтобы удалилось
00293             mWidgetChild.push_back(*iter);
00294             _destroyChildWidget(*iter);
00295         }
00296         mWidgetChildSkin.clear();
00297 
00298         mWidgetClient = nullptr;
00299     }
00300 
00301     Widget* Widget::baseCreateWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer, const std::string& _name, bool _template)
00302     {
00303         Widget* widget = nullptr;
00304 
00305         if (_template)
00306         {
00307             widget = WidgetManager::getInstance().createWidget(_style, _type, _skin, _coord, this, _style == WidgetStyle::Popup ? nullptr : this, _name);
00308             mWidgetChildSkin.push_back(widget);
00309         }
00310         else
00311         {
00312             if (mWidgetClient != nullptr)
00313             {
00314                 widget = mWidgetClient->baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name, _template);
00315                 onWidgetCreated(widget);
00316                 return widget;
00317             }
00318             else
00319             {
00320                 widget = WidgetManager::getInstance().createWidget(_style, _type, _skin, _coord, this, _style == WidgetStyle::Popup ? nullptr : this, _name);
00321                 mWidgetChild.push_back(widget);
00322             }
00323         }
00324 
00325         widget->setAlign(_align);
00326 
00327         // присоединяем виджет с уровню
00328         if (!_layer.empty() && widget->isRootWidget())
00329             LayerManager::getInstance().attachToLayerNode(_layer, widget);
00330 
00331         onWidgetCreated(widget);
00332 
00333         return widget;
00334     }
00335 
00336     Widget* Widget::createWidgetRealT(const std::string& _type, const std::string& _skin, const FloatCoord& _coord, Align _align, const std::string& _name)
00337     {
00338         return createWidgetT(_type, _skin, CoordConverter::convertFromRelative(_coord, getSize()), _align, _name);
00339     }
00340 
00341     void Widget::_updateView()
00342     {
00343         bool margin = mCroppedParent ? _checkMargin() : false;
00344 
00345         // вьюпорт стал битым
00346         if (margin)
00347         {
00348             // проверка на полный выход за границу
00349             if (_checkOutside())
00350             {
00351                 // запоминаем текущее состояние
00352                 mIsMargin = margin;
00353 
00354                 // скрываем
00355                 _setSubSkinVisible(false);
00356 
00357                 // вся иерархия должна быть проверенна
00358                 for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00359                     (*widget)->_updateView();
00360                 for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00361                     (*widget)->_updateView();
00362 
00363                 return;
00364             }
00365 
00366         }
00367         // мы не обрезаны и были нормальные
00368         else if (!mIsMargin)
00369         {
00370             _updateSkinItemView();
00371             return;
00372         }
00373 
00374         // запоминаем текущее состояние
00375         mIsMargin = margin;
00376 
00377         // если скин был скрыт, то покажем
00378         _setSubSkinVisible(true);
00379 
00380         // обновляем наших детей, а они уже решат обновлять ли своих детей
00381         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00382             (*widget)->_updateView();
00383         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00384             (*widget)->_updateView();
00385 
00386         _updateSkinItemView();
00387     }
00388 
00389     bool Widget::_setWidgetState(const std::string& _state)
00390     {
00391         return _setSkinItemState(_state);
00392     }
00393 
00394     void Widget::_destroyChildWidget(Widget* _widget)
00395     {
00396         MYGUI_ASSERT(nullptr != _widget, "invalid widget pointer");
00397 
00398         if (mParent != nullptr && mParent->getClientWidget() == this)
00399             mParent->onWidgetDestroy(_widget);
00400 
00401         onWidgetDestroy(_widget);
00402 
00403         VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
00404         if (iter != mWidgetChild.end())
00405         {
00406             // сохраняем указатель
00407             MyGUI::Widget* widget = *iter;
00408 
00409             // удаляем из списка
00410             mWidgetChild.erase(iter);
00411 
00412             // отписываем от всех
00413             WidgetManager::getInstance().unlinkFromUnlinkers(_widget);
00414 
00415             // непосредственное удаление
00416             WidgetManager::getInstance()._deleteWidget(widget);
00417         }
00418         else
00419         {
00420             MYGUI_EXCEPT("Widget '" << _widget->getName() << "' not found");
00421         }
00422     }
00423 
00424     // удаляет всех детей
00425     void Widget::_destroyAllChildWidget()
00426     {
00427         WidgetManager& manager = WidgetManager::getInstance();
00428         while (!mWidgetChild.empty())
00429         {
00430             // сразу себя отписывем, иначе вложенной удаление убивает все
00431             Widget* widget = mWidgetChild.back();
00432             mWidgetChild.pop_back();
00433 
00434             // отписываем от всех
00435             manager.unlinkFromUnlinkers(widget);
00436 
00437             // и сами удалим, так как его больше в списке нет
00438             WidgetManager::getInstance()._deleteWidget(widget);
00439         }
00440     }
00441 
00442     IntCoord Widget::getClientCoord()
00443     {
00444         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00445         if (mWidgetClient != nullptr)
00446             return mWidgetClient->getCoord();
00447         return IntCoord(0, 0, mCoord.width, mCoord.height);
00448     }
00449 
00450     void Widget::setAlpha(float _alpha)
00451     {
00452         if (mAlpha == _alpha)
00453             return;
00454         mAlpha = _alpha;
00455 
00456         _updateAlpha();
00457     }
00458 
00459     void Widget::_updateAlpha()
00460     {
00461         if (nullptr != mParent)
00462             mRealAlpha = mAlpha * (mInheritsAlpha ? mParent->_getRealAlpha() : ALPHA_MAX);
00463         else
00464             mRealAlpha = mAlpha;
00465 
00466         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00467             (*widget)->_updateAlpha();
00468         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00469             (*widget)->_updateAlpha();
00470 
00471         _setSkinItemAlpha(mRealAlpha);
00472     }
00473 
00474     void Widget::setInheritsAlpha(bool _inherits)
00475     {
00476         mInheritsAlpha = _inherits;
00477         _updateAlpha();
00478     }
00479 
00480     ILayerItem* Widget::getLayerItemByPoint(int _left, int _top) const
00481     {
00482         // проверяем попадание
00483         if (!mEnabled
00484             || !mVisible
00485             || (!getNeedMouseFocus() && !getInheritsPick())
00486             || !_checkPoint(_left, _top)
00487             // если есть маска, проверяем еще и по маске
00488             || !isMaskPickInside(IntPoint(_left - mCoord.left, _top - mCoord.top), mCoord)
00489             )
00490             return nullptr;
00491 
00492         // спрашиваем у детишек
00493         for (VectorWidgetPtr::const_reverse_iterator widget = mWidgetChild.rbegin(); widget != mWidgetChild.rend(); ++widget)
00494         {
00495             // общаемся только с послушными детьми
00496             if ((*widget)->mWidgetStyle == WidgetStyle::Popup)
00497                 continue;
00498 
00499             ILayerItem* item = (*widget)->getLayerItemByPoint(_left - mCoord.left, _top - mCoord.top);
00500             if (item != nullptr)
00501                 return item;
00502         }
00503         // спрашиваем у детишек скна
00504         for (VectorWidgetPtr::const_reverse_iterator widget = mWidgetChildSkin.rbegin(); widget != mWidgetChildSkin.rend(); ++widget)
00505         {
00506             ILayerItem* item = (*widget)->getLayerItemByPoint(_left - mCoord.left, _top - mCoord.top);
00507             if (item != nullptr)
00508                 return item;
00509         }
00510 
00511         // непослушные дети
00512         return getInheritsPick() ? nullptr : (ILayerItem*)(this);
00513     }
00514 
00515     void Widget::_updateAbsolutePoint()
00516     {
00517         // мы рут, нам не надо
00518         if (!mCroppedParent)
00519             return;
00520 
00521         mAbsolutePosition = mCroppedParent->getAbsolutePosition() + mCoord.point();
00522 
00523         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00524             (*widget)->_updateAbsolutePoint();
00525         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00526             (*widget)->_updateAbsolutePoint();
00527 
00528         _correctSkinItemView();
00529     }
00530 
00531     void Widget::_forcePick(Widget* _widget)
00532     {
00533         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00534         if (mWidgetClient != nullptr)
00535             mWidgetClient->_forcePick(_widget);
00536 
00537         VectorWidgetPtr::iterator item = std::remove(mWidgetChild.begin(), mWidgetChild.end(), _widget);
00538         if (item != mWidgetChild.end())
00539         {
00540             mWidgetChild.erase(item);
00541             mWidgetChild.insert(mWidgetChild.begin(), _widget);
00542         }
00543     }
00544 
00545     Widget* Widget::findWidget(const std::string& _name)
00546     {
00547         if (_name == mName)
00548             return this;
00549         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00550         if (mWidgetClient != nullptr)
00551             return mWidgetClient->findWidget(_name);
00552 
00553         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00554         {
00555             Widget* find = (*widget)->findWidget(_name);
00556             if (nullptr != find)
00557                 return find;
00558         }
00559         return nullptr;
00560     }
00561 
00562     void Widget::setRealPosition(const FloatPoint& _point)
00563     {
00564         setPosition(CoordConverter::convertFromRelative(_point, mCroppedParent == nullptr ? RenderManager::getInstance().getViewSize() : mCroppedParent->getSize()));
00565     }
00566 
00567     void Widget::setRealSize(const FloatSize& _size)
00568     {
00569         setSize(CoordConverter::convertFromRelative(_size, mCroppedParent == nullptr ? RenderManager::getInstance().getViewSize() : mCroppedParent->getSize()));
00570     }
00571 
00572     void Widget::setRealCoord(const FloatCoord& _coord)
00573     {
00574         setCoord(CoordConverter::convertFromRelative(_coord, mCroppedParent == nullptr ? RenderManager::getInstance().getViewSize() : mCroppedParent->getSize()));
00575     }
00576 
00577     void Widget::_setAlign(const IntSize& _oldsize, const IntSize& _newSize)
00578     {
00579         const IntSize& size = _newSize;//getParentSize();
00580 
00581         bool need_move = false;
00582         bool need_size = false;
00583         IntCoord coord = mCoord;
00584 
00585         // первоначальное выравнивание
00586         if (mAlign.isHStretch())
00587         {
00588             // растягиваем
00589             coord.width = mCoord.width + (size.width - _oldsize.width);
00590             need_size = true;
00591         }
00592         else if (mAlign.isRight())
00593         {
00594             // двигаем по правому краю
00595             coord.left = mCoord.left + (size.width - _oldsize.width);
00596             need_move = true;
00597         }
00598         else if (mAlign.isHCenter())
00599         {
00600             // выравнивание по горизонтали без растяжения
00601             coord.left = (size.width - mCoord.width) / 2;
00602             need_move = true;
00603         }
00604 
00605         if (mAlign.isVStretch())
00606         {
00607             // растягиваем
00608             coord.height = mCoord.height + (size.height - _oldsize.height);
00609             need_size = true;
00610         }
00611         else if (mAlign.isBottom())
00612         {
00613             // двигаем по нижнему краю
00614             coord.top = mCoord.top + (size.height - _oldsize.height);
00615             need_move = true;
00616         }
00617         else if (mAlign.isVCenter())
00618         {
00619             // выравнивание по вертикали без растяжения
00620             coord.top = (size.height - mCoord.height) / 2;
00621             need_move = true;
00622         }
00623 
00624         if (need_move)
00625         {
00626             if (need_size)
00627                 setCoord(coord);
00628             else
00629                 setPosition(coord.point());
00630         }
00631         else if (need_size)
00632         {
00633             setSize(coord.size());
00634         }
00635         else
00636         {
00637             _updateView(); // только если не вызвано передвижение и сайз
00638         }
00639     }
00640 
00641     void Widget::setPosition(const IntPoint& _point)
00642     {
00643         // обновляем абсолютные координаты
00644         mAbsolutePosition += _point - mCoord.point();
00645 
00646         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00647             (*widget)->_updateAbsolutePoint();
00648         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00649             (*widget)->_updateAbsolutePoint();
00650 
00651         mCoord = _point;
00652 
00653         _updateView();
00654     }
00655 
00656     void Widget::setSize(const IntSize& _size)
00657     {
00658         // устанавливаем новую координату а старую пускаем в расчеты
00659         IntSize old = mCoord.size();
00660         mCoord = _size;
00661 
00662         bool visible = true;
00663 
00664         // обновляем выравнивание
00665         bool margin = mCroppedParent ? _checkMargin() : false;
00666 
00667         if (margin)
00668         {
00669             // проверка на полный выход за границу
00670             if (_checkOutside())
00671             {
00672                 // скрываем
00673                 visible = false;
00674             }
00675         }
00676 
00677         _setSubSkinVisible(visible);
00678 
00679         // передаем старую координату , до вызова, текущая координата отца должна быть новой
00680         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00681             (*widget)->_setAlign(old, getSize());
00682         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00683             (*widget)->_setAlign(old, getSize());
00684 
00685         _setSkinItemAlign(old);
00686 
00687         // запоминаем текущее состояние
00688         mIsMargin = margin;
00689     }
00690 
00691     void Widget::setCoord(const IntCoord& _coord)
00692     {
00693         // обновляем абсолютные координаты
00694         mAbsolutePosition += _coord.point() - mCoord.point();
00695 
00696         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00697             (*widget)->_updateAbsolutePoint();
00698         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00699             (*widget)->_updateAbsolutePoint();
00700 
00701         // устанавливаем новую координату а старую пускаем в расчеты
00702         IntCoord old = mCoord;
00703         mCoord = _coord;
00704 
00705         bool visible = true;
00706 
00707         // обновляем выравнивание
00708         bool margin = mCroppedParent ? _checkMargin() : false;
00709 
00710         if (margin)
00711         {
00712             // проверка на полный выход за границу
00713             if (_checkOutside())
00714             {
00715                 // скрываем
00716                 visible = false;
00717             }
00718         }
00719 
00720         _setSubSkinVisible(visible);
00721 
00722         // передаем старую координату , до вызова, текущая координата отца должна быть новой
00723         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00724             (*widget)->_setAlign(old.size(), getSize());
00725         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00726             (*widget)->_setAlign(old.size(), getSize());
00727 
00728         _setSkinItemAlign(old.size());
00729 
00730         // запоминаем текущее состояние
00731         mIsMargin = margin;
00732     }
00733 
00734     void Widget::setAlign(Align _value)
00735     {
00736         mAlign = _value;
00737     }
00738 
00739     void Widget::detachFromWidget(const std::string& _layer)
00740     {
00741         std::string oldlayer = getLayer() != nullptr ? getLayer()->getName() : "";
00742 
00743         Widget* parent = getParent();
00744         if (parent)
00745         {
00746             // отдетачиваемся от лееров
00747             if ( ! isRootWidget() )
00748             {
00749                 detachFromLayerItemNode(true);
00750 
00751                 if (mWidgetStyle == WidgetStyle::Child)
00752                 {
00753                     mParent->removeChildItem(this);
00754                 }
00755                 else if (mWidgetStyle == WidgetStyle::Overlapped)
00756                 {
00757                     mParent->removeChildNode(this);
00758                 }
00759 
00760                 mWidgetStyle = WidgetStyle::Overlapped;
00761 
00762                 mCroppedParent = nullptr;
00763 
00764                 // обновляем координаты
00765                 mAbsolutePosition = mCoord.point();
00766 
00767                 for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00768                     (*widget)->_updateAbsolutePoint();
00769                 for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00770                     (*widget)->_updateAbsolutePoint();
00771 
00772                 // сбрасываем обрезку
00773                 mMargin.clear();
00774 
00775                 _updateView();
00776             }
00777 
00778             // нам нужен самый рутовый парент
00779             while (parent->getParent())
00780                 parent = parent->getParent();
00781 
00782             //mIWidgetCreator = parent->mIWidgetCreator;
00783             //mIWidgetCreator->_linkChildWidget(this);
00784             Gui::getInstance()._linkChildWidget(this);
00785             mParent->_unlinkChildWidget(this);
00786             mParent = nullptr;
00787         }
00788 
00789         if (!_layer.empty())
00790         {
00791             LayerManager::getInstance().attachToLayerNode(_layer, this);
00792         }
00793         else if (!oldlayer.empty())
00794         {
00795             LayerManager::getInstance().attachToLayerNode(oldlayer, this);
00796         }
00797 
00798         _updateAlpha();
00799     }
00800 
00801     void Widget::attachToWidget(Widget* _parent, WidgetStyle _style, const std::string& _layer)
00802     {
00803         MYGUI_ASSERT(_parent, "parent must be valid");
00804         MYGUI_ASSERT(_parent != this, "cyclic attach (attaching to self)");
00805 
00806         // attach to client if widget have it
00807         if (_parent->getClientWidget())
00808             _parent = _parent->getClientWidget();
00809 
00810         // проверяем на цикличность атача
00811         Widget* parent = _parent;
00812         while (parent->getParent())
00813         {
00814             MYGUI_ASSERT(parent != this, "cyclic attach");
00815             parent = parent->getParent();
00816         }
00817 
00818         // отдетачиваемся от всего
00819         detachFromWidget();
00820 
00821         mWidgetStyle = _style;
00822 
00823         if (_style == WidgetStyle::Popup)
00824         {
00825             //mIWidgetCreator->_unlinkChildWidget(this);
00826             //mIWidgetCreator = _parent;
00827             if (mParent == nullptr)
00828                 Gui::getInstance()._unlinkChildWidget(this);
00829             else
00830                 mParent->_unlinkChildWidget(this);
00831 
00832             mParent = _parent;
00833             mParent->_linkChildWidget(this);
00834 
00835             mCroppedParent = nullptr;
00836 
00837             if (!_layer.empty())
00838             {
00839                 LayerManager::getInstance().attachToLayerNode(_layer, this);
00840             }
00841         }
00842         else if (_style == WidgetStyle::Child)
00843         {
00844             LayerManager::getInstance().detachFromLayer(this);
00845 
00846             //mIWidgetCreator->_unlinkChildWidget(this);
00847             //mIWidgetCreator = _parent;
00848             if (mParent == nullptr)
00849                 Gui::getInstance()._unlinkChildWidget(this);
00850             else
00851                 mParent->_unlinkChildWidget(this);
00852 
00853             mParent = _parent;
00854             mParent->_linkChildWidget(this);
00855 
00856             mCroppedParent = _parent;
00857             mAbsolutePosition = _parent->getAbsolutePosition() + mCoord.point();
00858 
00859             for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00860                 (*widget)->_updateAbsolutePoint();
00861             for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00862                 (*widget)->_updateAbsolutePoint();
00863 
00864             mParent->addChildItem(this);
00865 
00866             _updateView();
00867         }
00868         else if (_style == WidgetStyle::Overlapped)
00869         {
00870             LayerManager::getInstance().detachFromLayer(this);
00871 
00872             //mIWidgetCreator->_unlinkChildWidget(this);
00873             //mIWidgetCreator = _parent;
00874             if (mParent == nullptr)
00875                 Gui::getInstance()._unlinkChildWidget(this);
00876             else
00877                 mParent->_unlinkChildWidget(this);
00878 
00879             mParent = _parent;
00880             mParent->_linkChildWidget(this);
00881 
00882             mCroppedParent = _parent;
00883             mAbsolutePosition = _parent->getAbsolutePosition() + mCoord.point();
00884 
00885             for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00886                 (*widget)->_updateAbsolutePoint();
00887             for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00888                 (*widget)->_updateAbsolutePoint();
00889 
00890             mParent->addChildNode(this);
00891 
00892             _updateView();
00893         }
00894 
00895         _updateAlpha();
00896     }
00897 
00898     void Widget::setWidgetStyle(WidgetStyle _style, const std::string& _layer)
00899     {
00900         if (_style == mWidgetStyle)
00901             return;
00902         if (nullptr == getParent())
00903             return;
00904 
00905         Widget* parent = mParent;
00906 
00907         detachFromWidget();
00908         attachToWidget(parent, _style, _layer);
00909         // ищем леер к которому мы присоедененны
00910     }
00911 
00912     Widget* Widget::createWidgetT(const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _name)
00913     {
00914         return baseCreateWidget(WidgetStyle::Child, _type, _skin, _coord, _align, "", _name, false);
00915     }
00916 
00917     Widget* Widget::createWidgetT(const std::string& _type, const std::string& _skin, int _left, int _top, int _width, int _height, Align _align, const std::string& _name)
00918     {
00919         return createWidgetT(_type, _skin, IntCoord(_left, _top, _width, _height), _align, _name);
00920     }
00921 
00922     Widget* Widget::createWidgetRealT(const std::string& _type, const std::string& _skin, float _left, float _top, float _width, float _height, Align _align, const std::string& _name)
00923     {
00924         return createWidgetRealT(_type, _skin, FloatCoord(_left, _top, _width, _height), _align, _name);
00925     }
00926 
00927     Widget* Widget::createWidgetT(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer, const std::string& _name)
00928     {
00929         return baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name, false);
00930     }
00931 
00932     EnumeratorWidgetPtr Widget::getEnumerator() const
00933     {
00934         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00935         if (mWidgetClient != nullptr)
00936             return mWidgetClient->getEnumerator();
00937         return Enumerator<VectorWidgetPtr>(mWidgetChild.begin(), mWidgetChild.end());
00938     }
00939 
00940     size_t Widget::getChildCount()
00941     {
00942         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00943         if (mWidgetClient != nullptr)
00944             return mWidgetClient->getChildCount();
00945         return mWidgetChild.size();
00946     }
00947 
00948     Widget* Widget::getChildAt(size_t _index)
00949     {
00950         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
00951         if (mWidgetClient != nullptr)
00952             return mWidgetClient->getChildAt(_index);
00953         MYGUI_ASSERT_RANGE(_index, mWidgetChild.size(), "Widget::getChildAt");
00954         return mWidgetChild[_index];
00955     }
00956 
00957     void Widget::baseUpdateEnable()
00958     {
00959         if (mEnabled)
00960             _setWidgetState("normal");
00961         else
00962             _setWidgetState("disabled");
00963     }
00964 
00965     void Widget::setVisible(bool _value)
00966     {
00967         if (mVisible == _value)
00968             return;
00969         mVisible = _value;
00970 
00971         _updateVisible();
00972     }
00973 
00974     void Widget::_updateVisible()
00975     {
00976         mInheritsVisible = mParent == nullptr || (mParent->getVisible() && mParent->getInheritedVisible());
00977         bool value = mVisible && mInheritsVisible;
00978 
00979         _setSkinItemVisible(value);
00980 
00981         for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
00982             (*widget)->_updateVisible();
00983         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
00984             (*widget)->_updateVisible();
00985 
00986         if (!value && InputManager::getInstance().getMouseFocusWidget() == this)
00987             InputManager::getInstance()._resetMouseFocusWidget();
00988     }
00989 
00990     void Widget::setEnabled(bool _value)
00991     {
00992         if (mEnabled == _value)
00993             return;
00994         mEnabled = _value;
00995 
00996         _updateEnabled();
00997     }
00998 
00999     void Widget::_updateEnabled()
01000     {
01001         mInheritsEnabled = mParent == nullptr || (mParent->getEnabled() && mParent->getInheritedEnabled());
01002         bool value = mEnabled && mInheritsEnabled;
01003 
01004         for (VectorWidgetPtr::iterator iter = mWidgetChild.begin(); iter != mWidgetChild.end(); ++iter)
01005             (*iter)->_updateEnabled();
01006         for (VectorWidgetPtr::iterator iter = mWidgetChildSkin.begin(); iter != mWidgetChildSkin.end(); ++iter)
01007             (*iter)->_updateEnabled();
01008 
01009         baseUpdateEnable();
01010 
01011         if (!value)
01012             InputManager::getInstance().unlinkWidget(this);
01013     }
01014 
01015     void Widget::setColour(const Colour& _value)
01016     {
01017         _setSkinItemColour(_value);
01018 
01019         for (VectorWidgetPtr::iterator widget = mWidgetChildSkin.begin(); widget != mWidgetChildSkin.end(); ++widget)
01020             (*widget)->setColour(_value);
01021     }
01022 
01023     IntSize Widget::getParentSize() const
01024     {
01025         if (mCroppedParent)
01026             return static_cast<Widget*>(mCroppedParent)->getSize();
01027         if (getLayer())
01028             return getLayer()->getSize();
01029 
01030         return RenderManager::getInstance().getViewSize();
01031     }
01032 
01033     void Widget::_resetContainer(bool _updateOnly)
01034     {
01035         if (getNeedToolTip())
01036             ToolTipManager::getInstance()._unlinkWidget(this);
01037     }
01038 
01039     bool Widget::_checkPoint(int _left, int _top) const
01040     {
01041         return ! ((_getViewLeft() > _left) || (_getViewTop() > _top) || (_getViewRight() < _left) || (_getViewBottom() < _top));
01042     }
01043 
01044     void Widget::_linkChildWidget(Widget* _widget)
01045     {
01046         VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
01047         MYGUI_ASSERT(iter == mWidgetChild.end(), "widget already exist");
01048         mWidgetChild.push_back(_widget);
01049     }
01050 
01051     void Widget::_unlinkChildWidget(Widget* _widget)
01052     {
01053         VectorWidgetPtr::iterator iter = std::remove(mWidgetChild.begin(), mWidgetChild.end(), _widget);
01054         MYGUI_ASSERT(iter != mWidgetChild.end(), "widget not found");
01055         mWidgetChild.erase(iter);
01056     }
01057 
01058     void Widget::shutdownOverride()
01059     {
01060     }
01061 
01062     void Widget::initialiseOverride()
01063     {
01064     }
01065 
01066     void Widget::setSkinProperty(ResourceSkin* _info)
01067     {
01068         const MapString& properties = _info->getProperties();
01069         for (MapString::const_iterator item = properties.begin(); item != properties.end(); ++item)
01070             setProperty((*item).first, (*item).second);
01071     }
01072 
01073     void Widget::setProperty(const std::string& _key, const std::string& _value)
01074     {
01075         std::string key = _key;
01076         std::string value = _value;
01077 
01078         if (BackwardCompatibility::checkProperty(this, key, value))
01079         {
01080             size_t index = key.find("_");
01081             if (index != std::string::npos)
01082             {
01083                 MYGUI_LOG(Warning, "Widget property '" << key << "' have type prefix - use '" << key.substr(index + 1) << "' instead [" << LayoutManager::getInstance().getCurrentLayout() << "]");
01084                 key = key.substr(index + 1);
01085             }
01086 
01087             setPropertyOverride(key, value);
01088         }
01089     }
01090 
01091     VectorWidgetPtr Widget::getSkinWidgetsByName(const std::string& _name)
01092     {
01093         VectorWidgetPtr result;
01094 
01095         for (VectorWidgetPtr::iterator iter = mWidgetChildSkin.begin(); iter != mWidgetChildSkin.end(); ++iter)
01096             (*iter)->findWidgets(_name, result);
01097 
01098         return result;
01099     }
01100 
01101     void Widget::findWidgets(const std::string& _name, VectorWidgetPtr& _result)
01102     {
01103         if (_name == mName)
01104             _result.push_back(this);
01105 
01106         MYGUI_ASSERT(mWidgetClient != this, "mWidgetClient can not be this widget");
01107         if (mWidgetClient != nullptr)
01108         {
01109             mWidgetClient->findWidgets(_name, _result);
01110         }
01111         else
01112         {
01113             for (VectorWidgetPtr::iterator widget = mWidgetChild.begin(); widget != mWidgetChild.end(); ++widget)
01114                 (*widget)->findWidgets(_name, _result);
01115         }
01116     }
01117 
01118     void Widget::destroySkinWidget(Widget* _widget)
01119     {
01120         mWidgetChild.push_back(_widget);
01121         WidgetManager::getInstance().destroyWidget(_widget);
01122     }
01123 
01124     void Widget::onWidgetCreated(Widget* _widget)
01125     {
01126     }
01127 
01128     void Widget::onWidgetDestroy(Widget* _widget)
01129     {
01130     }
01131 
01132     void Widget::setWidgetClient(Widget* _widget)
01133     {
01134         mWidgetClient = _widget;
01135     }
01136 
01137     Widget* Widget::_createSkinWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer, const std::string& _name)
01138     {
01139         return baseCreateWidget(_style, _type, _skin, _coord, _align, _layer, _name, true);
01140     }
01141 
01142     void Widget::setPropertyOverride(const std::string& _key, const std::string& _value)
01143     {
01145         if (_key == "Position")
01146             setPosition(utility::parseValue<IntPoint>(_value));
01148         else if (_key == "Size")
01149             setSize(utility::parseValue<IntSize>(_value));
01151         else if (_key == "Coord")
01152             setCoord(utility::parseValue<IntCoord>(_value));
01154         else if (_key == "Visible")
01155             setVisible(utility::parseValue<bool>(_value));
01156         else if (_key == "Alpha")
01157             setAlpha(utility::parseValue<float>(_value));
01158         else if (_key == "Colour")
01159             setColour(utility::parseValue<Colour>(_value));
01160         else if (_key == "InheritsAlpha")
01161             setInheritsAlpha(utility::parseValue<bool>(_value));
01162         else if (_key == "InheritsPick")
01163             setInheritsPick(utility::parseValue<bool>(_value));
01164         else if (_key == "MaskPick")
01165             setMaskPick(_value);
01166         else if (_key == "NeedKey")
01167             setNeedKeyFocus(utility::parseValue<bool>(_value));
01168         else if (_key == "NeedMouse")
01169             setNeedMouseFocus(utility::parseValue<bool>(_value));
01170         else if (_key == "Enabled")
01171             setEnabled(utility::parseValue<bool>(_value));
01172         else if (_key == "NeedToolTip")
01173             setNeedToolTip(utility::parseValue<bool>(_value));
01174         else if (_key == "Pointer")
01175             setPointer(_value);
01176         else
01177         {
01178             MYGUI_LOG(Warning, "Widget property '" << _key << "' not found" << " [" << LayoutManager::getInstance().getCurrentLayout() << "]");
01179             return;
01180         }
01181 
01182         eventChangeProperty(this, _key, _value);
01183     }
01184 
01185     void Widget::setPosition(int _left, int _top)
01186     {
01187         setPosition(IntPoint(_left, _top));
01188     }
01189 
01190     void Widget::setSize(int _width, int _height)
01191     {
01192         setSize(IntSize(_width, _height));
01193     }
01194 
01195     void Widget::setCoord(int _left, int _top, int _width, int _height)
01196     {
01197         setCoord(IntCoord(_left, _top, _width, _height));
01198     }
01199 
01200     void Widget::setRealPosition(float _left, float _top)
01201     {
01202         setRealPosition(FloatPoint(_left, _top));
01203     }
01204 
01205     void Widget::setRealSize(float _width, float _height)
01206     {
01207         setRealSize(FloatSize(_width, _height));
01208     }
01209 
01210     void Widget::setRealCoord(float _left, float _top, float _width, float _height)
01211     {
01212         setRealCoord(FloatCoord(_left, _top, _width, _height));
01213     }
01214 
01215     const std::string& Widget::getName() const
01216     {
01217         return mName;
01218     }
01219 
01220     bool Widget::getVisible() const
01221     {
01222         return mVisible;
01223     }
01224 
01225     Align Widget::getAlign() const
01226     {
01227         return mAlign;
01228     }
01229 
01230     float Widget::getAlpha() const
01231     {
01232         return mAlpha;
01233     }
01234 
01235     bool Widget::getInheritsAlpha()  const
01236     {
01237         return mInheritsAlpha;
01238     }
01239 
01240     bool Widget::isRootWidget() const
01241     {
01242         return nullptr == mCroppedParent;
01243     }
01244 
01245     Widget* Widget::getParent() const
01246     {
01247         return mParent;
01248     }
01249 
01250     void Widget::setEnabledSilent(bool _value)
01251     {
01252         mEnabled = _value;
01253     }
01254 
01255     bool Widget::getEnabled() const
01256     {
01257         return mEnabled;
01258     }
01259 
01260     Widget* Widget::getClientWidget()
01261     {
01262         return mWidgetClient;
01263     }
01264 
01265     WidgetStyle Widget::getWidgetStyle() const
01266     {
01267         return mWidgetStyle;
01268     }
01269 
01270     size_t Widget::_getItemIndex(Widget* _item)
01271     {
01272         return ITEM_NONE;
01273     }
01274 
01275     void Widget::_setContainer(Widget* _value)
01276     {
01277         mContainer = _value;
01278     }
01279 
01280     Widget* Widget::_getContainer()
01281     {
01282         return mContainer;
01283     }
01284 
01285     size_t Widget::_getContainerIndex(const IntPoint& _point)
01286     {
01287         return ITEM_NONE;
01288     }
01289 
01290     const IntCoord& Widget::getLayerItemCoord() const
01291     {
01292         return mCoord;
01293     }
01294 
01295     float Widget::_getRealAlpha() const
01296     {
01297         return mRealAlpha;
01298     }
01299 
01300     bool Widget::getInheritedEnabled() const
01301     {
01302         return mInheritsEnabled;
01303     }
01304 
01305     bool Widget::getInheritedVisible() const
01306     {
01307         return mInheritsVisible;
01308     }
01309 
01310     void Widget::resizeLayerItemView(const IntSize& _oldView, const IntSize& _newView)
01311     {
01312         _setAlign(_oldView, _newView);
01313     }
01314 
01315 } // namespace MyGUI