MyGUI  3.0.1
MyGUI_ResourceSkin.cpp
Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_ResourceSkin.h"
00025 #include "MyGUI_FactoryManager.h"
00026 #include "MyGUI_LanguageManager.h"
00027 
00028 namespace MyGUI
00029 {
00030 
00031     ResourceSkin::ResourceSkin()
00032     {
00033     }
00034 
00035     void ResourceSkin::deserialization(xml::ElementPtr _node, Version _version)
00036     {
00037         Base::deserialization(_node, _version);
00038 
00039         // парсим атрибуты скина
00040         std::string name, texture, tmp;
00041         IntSize size;
00042         _node->findAttribute("name", name);
00043         _node->findAttribute("texture", texture);
00044         if (_node->findAttribute("size", tmp)) size = IntSize::parse(tmp);
00045 
00046         LanguageManager& localizator = LanguageManager::getInstance();
00047 
00048         // вспомогательный класс для биндинга сабскинов
00049         SubWidgetBinding bind;
00050 
00051         // поддержка замены тегов в скинах
00052         if (_version >= Version(1, 1))
00053         {
00054             texture = localizator.replaceTags(texture);
00055         }
00056 
00057         setInfo(size, texture);
00058 
00059         // проверяем маску
00060         if (_node->findAttribute("mask", tmp))
00061         {
00062             if (!loadMask(tmp))
00063             {
00064                 MYGUI_LOG(Error, "Skin: mask not load '" << tmp << "'");
00065             }
00066         }
00067 
00068         // берем детей и крутимся, цикл с саб скинами
00069         xml::ElementEnumerator basis = _node->getElementEnumerator();
00070         while (basis.next())
00071         {
00072             if (basis->getName() == "Property")
00073             {
00074                 // загружаем свойства
00075                 std::string key, value;
00076                 if (!basis->findAttribute("key", key)) continue;
00077                 if (!basis->findAttribute("value", value)) continue;
00078 
00079                 // поддержка замены тегов в скинах
00080                 if (_version >= Version(1, 1))
00081                 {
00082                     value = localizator.replaceTags(value);
00083                 }
00084 
00085                 // добавляем свойство
00086                 addProperty(key, value);
00087             }
00088             else if (basis->getName() == "Child")
00089             {
00090                 ChildSkinInfo child(
00091                     basis->findAttribute("type"),
00092                     WidgetStyle::parse(basis->findAttribute("style")),
00093                     basis->findAttribute("skin"),
00094                     IntCoord::parse(basis->findAttribute("offset")),
00095                     Align::parse(basis->findAttribute("align")),
00096                     basis->findAttribute("layer"),
00097                     basis->findAttribute("name")
00098                     );
00099 
00100                 xml::ElementEnumerator child_params = basis->getElementEnumerator();
00101                 while (child_params.next("Property"))
00102                     child.addParam(child_params->findAttribute("key"), child_params->findAttribute("value"));
00103 
00104                 addChild(child);
00105                 //continue;
00106             }
00107             else if (basis->getName() == "BasisSkin")
00108             {
00109                 // парсим атрибуты
00110                 std::string basisSkinType, tmp_str;
00111                 IntCoord offset;
00112                 Align align = Align::Default;
00113                 basis->findAttribute("type", basisSkinType);
00114                 if (basis->findAttribute("offset", tmp_str)) offset = IntCoord::parse(tmp_str);
00115                 if (basis->findAttribute("align", tmp_str)) align = Align::parse(tmp_str);
00116 
00117                 bind.create(offset, align, basisSkinType);
00118 
00119                 // берем детей и крутимся, цикл со стейтами
00120                 xml::ElementEnumerator state = basis->getElementEnumerator();
00121 
00122                 // проверяем на новый формат стейтов
00123                 bool new_format = false;
00124                 // если версия меньше 1.0 то переименовываем стейты
00125                 if (_version < Version(1, 0))
00126                 {
00127                     while (state.next())
00128                     {
00129                         if (state->getName() == "State")
00130                         {
00131                             const std::string& name_state = state->findAttribute("name");
00132                             if ((name_state == "normal_checked") || (state->findAttribute("name") == "normal_check"))
00133                             {
00134                                 new_format = true;
00135                                 break;
00136                             }
00137                         }
00138                     }
00139                     // обновляем
00140                     state = basis->getElementEnumerator();
00141                 }
00142 
00143                 while (state.next())
00144                 {
00145                     if (state->getName() == "State")
00146                     {
00147                         // парсим атрибуты стейта
00148                         std::string basisStateName;
00149                         state->findAttribute("name", basisStateName);
00150 
00151                         // если версия меньше 1.0 то переименовываем стейты
00152                         if (_version < Version(1, 0))
00153                         {
00154                             // это обсолет новых типов
00155                             if (basisStateName == "disable_check") basisStateName = "disabled_checked";
00156                             else if (basisStateName == "normal_check") basisStateName = "normal_checked";
00157                             else if (basisStateName == "active_check") basisStateName = "highlighted_checked";
00158                             else if (basisStateName == "pressed_check") basisStateName = "pushed_checked";
00159                             else if (basisStateName == "disable") basisStateName = "disabled";
00160                             else if (basisStateName == "active") basisStateName = "highlighted";
00161                             else if (basisStateName == "select") basisStateName = "pushed";
00162                             else if (basisStateName == "pressed")
00163                             {
00164                                 if (new_format) basisStateName = "pushed";
00165                                 else basisStateName = "normal_checked";
00166                             }
00167                         }
00168 
00169                         // конвертируем инфу о стейте
00170                         IStateInfo* data = nullptr;
00171                         IObject* object = FactoryManager::getInstance().createObject("BasisSkin/State", basisSkinType);
00172                         if (object != nullptr)
00173                         {
00174                             data = object->castType<IStateInfo>();
00175                             data->deserialization(state.current(), _version);
00176                         }
00177 
00178                         // добавляем инфо о стайте
00179                         bind.add(basisStateName, data, name);
00180                     }
00181                 }
00182 
00183                 // теперь всё вместе добавляем в скин
00184                 addInfo(bind);
00185             }
00186 
00187         }
00188     }
00189 
00190     void ResourceSkin::setInfo(const IntSize& _size, const std::string &_texture)
00191     {
00192         mSize = _size;
00193         mTexture = _texture;
00194     }
00195 
00196     void ResourceSkin::addInfo(const SubWidgetBinding& _bind)
00197     {
00198         checkState(_bind.mStates);
00199         mBasis.push_back(SubWidgetInfo(_bind.mType, _bind.mOffset, _bind.mAlign));
00200         checkBasis();
00201         fillState(_bind.mStates, mBasis.size()-1);
00202     }
00203 
00204     void ResourceSkin::addProperty(const std::string &_key, const std::string &_value)
00205     {
00206         mProperties[_key] = _value;
00207     }
00208 
00209     void ResourceSkin::addChild(const ChildSkinInfo& _child)
00210     {
00211         mChilds.push_back(_child);
00212     }
00213 
00214     bool ResourceSkin::loadMask(const std::string& _file)
00215     {
00216         return mMaskPeek.load(_file);
00217     }
00218 
00219     void ResourceSkin::clear()
00220     {
00221         for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter!=mStates.end(); ++iter)
00222         {
00223             for (VectorStateInfo::iterator iter2=iter->second.begin(); iter2!=iter->second.end(); ++iter2)
00224             {
00225                 delete *iter2;
00226             }
00227         }
00228     }
00229 
00230     void ResourceSkin::checkState(const MapStateInfo& _states)
00231     {
00232         for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
00233         {
00234             checkState(iter->first);
00235         }
00236     }
00237 
00238     void ResourceSkin::checkState(const std::string& _name)
00239     {
00240         // ищем такой же ключ
00241         MapWidgetStateInfo::const_iterator iter = mStates.find(_name);
00242         if (iter == mStates.end())
00243         {
00244             // добавляем новый стейт
00245             mStates[_name] = VectorStateInfo();
00246         }
00247     }
00248 
00249     void ResourceSkin::checkBasis()
00250     {
00251         // и увеличиваем размер смещений по колличеству сабвиджетов
00252         for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter!=mStates.end(); ++iter)
00253         {
00254             iter->second.resize(mBasis.size());
00255         }
00256     }
00257 
00258     void ResourceSkin::fillState(const MapStateInfo& _states, size_t _index)
00259     {
00260         for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
00261         {
00262             mStates[iter->first][_index] = iter->second;
00263         }
00264     }
00265 
00266 } // namespace MyGUI