MyGUI  3.2.1
MyGUI_ResourceSkin.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_ResourceSkin.h"
00009 #include "MyGUI_FactoryManager.h"
00010 #include "MyGUI_LanguageManager.h"
00011 #include "MyGUI_SubWidgetManager.h"
00012 
00013 namespace MyGUI
00014 {
00015 
00016     ResourceSkin::ResourceSkin()
00017     {
00018     }
00019 
00020     ResourceSkin::~ResourceSkin()
00021     {
00022         for (MapWidgetStateInfo::iterator item = mStates.begin(); item != mStates.end(); ++ item)
00023         {
00024             for (VectorStateInfo::iterator info = (*item).second.begin(); info != (*item).second.end(); ++ info)
00025                 delete (*info);
00026         }
00027         mStates.clear();
00028     }
00029 
00030     void ResourceSkin::deserialization(xml::ElementPtr _node, Version _version)
00031     {
00032         Base::deserialization(_node, _version);
00033 
00034         std::string stateCategory = SubWidgetManager::getInstance().getStateCategoryName();
00035 
00036         // парсим атрибуты скина
00037         std::string name, texture, tmp;
00038         IntSize size;
00039         _node->findAttribute("name", name);
00040         _node->findAttribute("texture", texture);
00041         if (_node->findAttribute("size", tmp)) size = IntSize::parse(tmp);
00042 
00043         LanguageManager& localizator = LanguageManager::getInstance();
00044 
00045         // вспомогательный класс для биндинга сабскинов
00046         SubWidgetBinding bind;
00047 
00048         // tags replacement support for Skins
00049         if (_version >= Version(1, 1))
00050         {
00051             texture = localizator.replaceTags(texture);
00052         }
00053 
00054         setInfo(size, texture);
00055 
00056         // проверяем маску
00057         if (_node->findAttribute("mask", tmp))
00058             addProperty("MaskPick", tmp);
00059 
00060         // берем детей и крутимся, цикл с саб скинами
00061         xml::ElementEnumerator basis = _node->getElementEnumerator();
00062         while (basis.next())
00063         {
00064             if (basis->getName() == "Property")
00065             {
00066                 // загружаем свойства
00067                 std::string key, value;
00068                 if (!basis->findAttribute("key", key))
00069                     continue;
00070                 if (!basis->findAttribute("value", value))
00071                     continue;
00072 
00073                 // tags replacement support for Skins
00074                 if (_version >= Version(1, 1))
00075                 {
00076                     value = localizator.replaceTags(value);
00077                 }
00078 
00079                 // добавляем свойство
00080                 addProperty(key, value);
00081             }
00082             else if (basis->getName() == "Child")
00083             {
00084                 ChildSkinInfo child(
00085                     basis->findAttribute("type"),
00086                     WidgetStyle::parse(basis->findAttribute("style")),
00087                     basis->findAttribute("skin"),
00088                     IntCoord::parse(basis->findAttribute("offset")),
00089                     Align::parse(basis->findAttribute("align")),
00090                     basis->findAttribute("layer"),
00091                     basis->findAttribute("name"));
00092 
00093                 xml::ElementEnumerator child_params = basis->getElementEnumerator();
00094                 while (child_params.next("Property"))
00095                     child.addParam(child_params->findAttribute("key"), child_params->findAttribute("value"));
00096 
00097                 addChild(child);
00098                 //continue;
00099             }
00100             else if (basis->getName() == "BasisSkin")
00101             {
00102                 // парсим атрибуты
00103                 std::string basisSkinType, tmp_str;
00104                 IntCoord offset;
00105                 Align align = Align::Default;
00106                 basis->findAttribute("type", basisSkinType);
00107                 if (basis->findAttribute("offset", tmp_str))
00108                     offset = IntCoord::parse(tmp_str);
00109                 if (basis->findAttribute("align", tmp_str))
00110                     align = Align::parse(tmp_str);
00111 
00112                 bind.create(offset, align, basisSkinType);
00113 
00114                 // берем детей и крутимся, цикл со стейтами
00115                 xml::ElementEnumerator state = basis->getElementEnumerator();
00116 
00117                 // проверяем на новый формат стейтов
00118                 bool new_format = false;
00119                 // если версия меньше 1.0 то переименовываем стейты
00120                 if (_version < Version(1, 0))
00121                 {
00122                     while (state.next())
00123                     {
00124                         if (state->getName() == "State")
00125                         {
00126                             const std::string& name_state = state->findAttribute("name");
00127                             if ((name_state == "normal_checked") || (state->findAttribute("name") == "normal_check"))
00128                             {
00129                                 new_format = true;
00130                                 break;
00131                             }
00132                         }
00133                     }
00134                     // обновляем
00135                     state = basis->getElementEnumerator();
00136                 }
00137 
00138                 while (state.next())
00139                 {
00140                     if (state->getName() == "State")
00141                     {
00142                         // парсим атрибуты стейта
00143                         std::string basisStateName;
00144                         state->findAttribute("name", basisStateName);
00145 
00146                         // если версия меньше 1.0 то переименовываем стейты
00147                         if (_version < Version(1, 0))
00148                         {
00149                             // это обсолет новых типов
00150                             if (basisStateName == "disable_check")
00151                                 basisStateName = "disabled_checked";
00152                             else if (basisStateName == "normal_check")
00153                                 basisStateName = "normal_checked";
00154                             else if (basisStateName == "active_check")
00155                                 basisStateName = "highlighted_checked";
00156                             else if (basisStateName == "pressed_check")
00157                                 basisStateName = "pushed_checked";
00158                             else if (basisStateName == "disable")
00159                                 basisStateName = "disabled";
00160                             else if (basisStateName == "active")
00161                                 basisStateName = "highlighted";
00162                             else if (basisStateName == "select")
00163                                 basisStateName = "pushed";
00164                             else if (basisStateName == "pressed")
00165                             {
00166                                 if (new_format)
00167                                     basisStateName = "pushed";
00168                                 else
00169                                     basisStateName = "normal_checked";
00170                             }
00171                         }
00172 
00173                         // конвертируем инфу о стейте
00174                         IStateInfo* data = nullptr;
00175                         IObject* object = FactoryManager::getInstance().createObject(stateCategory, basisSkinType);
00176                         if (object != nullptr)
00177                         {
00178                             data = object->castType<IStateInfo>();
00179                             data->deserialization(state.current(), _version);
00180                         }
00181 
00182                         // добавляем инфо о стайте
00183                         bind.add(basisStateName, data, name);
00184                     }
00185                 }
00186 
00187                 // теперь всё вместе добавляем в скин
00188                 addInfo(bind);
00189             }
00190 
00191         }
00192     }
00193 
00194     void ResourceSkin::setInfo(const IntSize& _size, const std::string& _texture)
00195     {
00196         mSize = _size;
00197         mTexture = _texture;
00198     }
00199 
00200     void ResourceSkin::addInfo(const SubWidgetBinding& _bind)
00201     {
00202         checkState(_bind.mStates);
00203         mBasis.push_back(SubWidgetInfo(_bind.mType, _bind.mOffset, _bind.mAlign));
00204         checkBasis();
00205         fillState(_bind.mStates, mBasis.size() - 1);
00206     }
00207 
00208     void ResourceSkin::addProperty(const std::string& _key, const std::string& _value)
00209     {
00210         mProperties[_key] = _value;
00211     }
00212 
00213     void ResourceSkin::addChild(const ChildSkinInfo& _child)
00214     {
00215         mChilds.push_back(_child);
00216     }
00217 
00218     void ResourceSkin::clear()
00219     {
00220         for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter != mStates.end(); ++iter)
00221         {
00222             for (VectorStateInfo::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2)
00223             {
00224                 delete *iter2;
00225             }
00226         }
00227     }
00228 
00229     void ResourceSkin::checkState(const MapStateInfo& _states)
00230     {
00231         for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
00232         {
00233             checkState(iter->first);
00234         }
00235     }
00236 
00237     void ResourceSkin::checkState(const std::string& _name)
00238     {
00239         // ищем такой же ключ
00240         MapWidgetStateInfo::const_iterator iter = mStates.find(_name);
00241         if (iter == mStates.end())
00242         {
00243             // добавляем новый стейт
00244             mStates[_name] = VectorStateInfo();
00245         }
00246     }
00247 
00248     void ResourceSkin::checkBasis()
00249     {
00250         // и увеличиваем размер смещений по колличеству сабвиджетов
00251         for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter != mStates.end(); ++iter)
00252         {
00253             iter->second.resize(mBasis.size());
00254         }
00255     }
00256 
00257     void ResourceSkin::fillState(const MapStateInfo& _states, size_t _index)
00258     {
00259         for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
00260         {
00261             mStates[iter->first][_index] = iter->second;
00262         }
00263     }
00264 
00265     const IntSize& ResourceSkin::getSize() const
00266     {
00267         return mSize;
00268     }
00269 
00270     const std::string& ResourceSkin::getTextureName() const
00271     {
00272         return mTexture;
00273     }
00274 
00275     const VectorSubWidgetInfo& ResourceSkin::getBasisInfo() const
00276     {
00277         return mBasis;
00278     }
00279 
00280     const MapWidgetStateInfo& ResourceSkin::getStateInfo() const
00281     {
00282         return mStates;
00283     }
00284 
00285     const MapString& ResourceSkin::getProperties() const
00286     {
00287         return mProperties;
00288     }
00289 
00290     const VectorChildSkinInfo& ResourceSkin::getChild() const
00291     {
00292         return mChilds;
00293     }
00294 
00295     const std::string& ResourceSkin::getSkinName() const
00296     {
00297         return mSkinName;
00298     }
00299 
00300 } // namespace MyGUI