MyGUI  3.0.3
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     ResourceSkin::~ResourceSkin()
00036     {
00037         for (MapWidgetStateInfo::iterator item = mStates.begin(); item != mStates.end(); ++ item)
00038         {
00039             for (VectorStateInfo::iterator info = (*item).second.begin(); info != (*item).second.end(); ++ info)
00040                 delete (*info);
00041         }
00042         mStates.clear();
00043     }
00044 
00045     void ResourceSkin::deserialization(xml::ElementPtr _node, Version _version)
00046     {
00047         Base::deserialization(_node, _version);
00048 
00049         // парсим атрибуты скина
00050         std::string name, texture, tmp;
00051         IntSize size;
00052         _node->findAttribute("name", name);
00053         _node->findAttribute("texture", texture);
00054         if (_node->findAttribute("size", tmp)) size = IntSize::parse(tmp);
00055 
00056         LanguageManager& localizator = LanguageManager::getInstance();
00057 
00058         // вспомогательный класс для биндинга сабскинов
00059         SubWidgetBinding bind;
00060 
00061         // поддержка замены тегов в скинах
00062         if (_version >= Version(1, 1))
00063         {
00064             texture = localizator.replaceTags(texture);
00065         }
00066 
00067         setInfo(size, texture);
00068 
00069         // проверяем маску
00070         if (_node->findAttribute("mask", tmp))
00071         {
00072             if (!loadMask(tmp))
00073             {
00074                 MYGUI_LOG(Error, "Skin: mask not load '" << tmp << "'");
00075             }
00076         }
00077 
00078         // берем детей и крутимся, цикл с саб скинами
00079         xml::ElementEnumerator basis = _node->getElementEnumerator();
00080         while (basis.next())
00081         {
00082             if (basis->getName() == "Property")
00083             {
00084                 // загружаем свойства
00085                 std::string key, value;
00086                 if (!basis->findAttribute("key", key)) continue;
00087                 if (!basis->findAttribute("value", value)) continue;
00088 
00089                 // поддержка замены тегов в скинах
00090                 if (_version >= Version(1, 1))
00091                 {
00092                     value = localizator.replaceTags(value);
00093                 }
00094 
00095                 // добавляем свойство
00096                 addProperty(key, value);
00097             }
00098             else if (basis->getName() == "Child")
00099             {
00100                 ChildSkinInfo child(
00101                     basis->findAttribute("type"),
00102                     WidgetStyle::parse(basis->findAttribute("style")),
00103                     basis->findAttribute("skin"),
00104                     IntCoord::parse(basis->findAttribute("offset")),
00105                     Align::parse(basis->findAttribute("align")),
00106                     basis->findAttribute("layer"),
00107                     basis->findAttribute("name")
00108                     );
00109 
00110                 xml::ElementEnumerator child_params = basis->getElementEnumerator();
00111                 while (child_params.next("Property"))
00112                     child.addParam(child_params->findAttribute("key"), child_params->findAttribute("value"));
00113 
00114                 addChild(child);
00115                 //continue;
00116             }
00117             else if (basis->getName() == "BasisSkin")
00118             {
00119                 // парсим атрибуты
00120                 std::string basisSkinType, tmp_str;
00121                 IntCoord offset;
00122                 Align align = Align::Default;
00123                 basis->findAttribute("type", basisSkinType);
00124                 if (basis->findAttribute("offset", tmp_str)) offset = IntCoord::parse(tmp_str);
00125                 if (basis->findAttribute("align", tmp_str)) align = Align::parse(tmp_str);
00126 
00127                 bind.create(offset, align, basisSkinType);
00128 
00129                 // берем детей и крутимся, цикл со стейтами
00130                 xml::ElementEnumerator state = basis->getElementEnumerator();
00131 
00132                 // проверяем на новый формат стейтов
00133                 bool new_format = false;
00134                 // если версия меньше 1.0 то переименовываем стейты
00135                 if (_version < Version(1, 0))
00136                 {
00137                     while (state.next())
00138                     {
00139                         if (state->getName() == "State")
00140                         {
00141                             const std::string& name_state = state->findAttribute("name");
00142                             if ((name_state == "normal_checked") || (state->findAttribute("name") == "normal_check"))
00143                             {
00144                                 new_format = true;
00145                                 break;
00146                             }
00147                         }
00148                     }
00149                     // обновляем
00150                     state = basis->getElementEnumerator();
00151                 }
00152 
00153                 while (state.next())
00154                 {
00155                     if (state->getName() == "State")
00156                     {
00157                         // парсим атрибуты стейта
00158                         std::string basisStateName;
00159                         state->findAttribute("name", basisStateName);
00160 
00161                         // если версия меньше 1.0 то переименовываем стейты
00162                         if (_version < Version(1, 0))
00163                         {
00164                             // это обсолет новых типов
00165                             if (basisStateName == "disable_check") basisStateName = "disabled_checked";
00166                             else if (basisStateName == "normal_check") basisStateName = "normal_checked";
00167                             else if (basisStateName == "active_check") basisStateName = "highlighted_checked";
00168                             else if (basisStateName == "pressed_check") basisStateName = "pushed_checked";
00169                             else if (basisStateName == "disable") basisStateName = "disabled";
00170                             else if (basisStateName == "active") basisStateName = "highlighted";
00171                             else if (basisStateName == "select") basisStateName = "pushed";
00172                             else if (basisStateName == "pressed")
00173                             {
00174                                 if (new_format) basisStateName = "pushed";
00175                                 else basisStateName = "normal_checked";
00176                             }
00177                         }
00178 
00179                         // конвертируем инфу о стейте
00180                         IStateInfo* data = nullptr;
00181                         IObject* object = FactoryManager::getInstance().createObject("BasisSkin/State", basisSkinType);
00182                         if (object != nullptr)
00183                         {
00184                             data = object->castType<IStateInfo>();
00185                             data->deserialization(state.current(), _version);
00186                         }
00187 
00188                         // добавляем инфо о стайте
00189                         bind.add(basisStateName, data, name);
00190                     }
00191                 }
00192 
00193                 // теперь всё вместе добавляем в скин
00194                 addInfo(bind);
00195             }
00196 
00197         }
00198     }
00199 
00200     void ResourceSkin::setInfo(const IntSize& _size, const std::string &_texture)
00201     {
00202         mSize = _size;
00203         mTexture = _texture;
00204     }
00205 
00206     void ResourceSkin::addInfo(const SubWidgetBinding& _bind)
00207     {
00208         checkState(_bind.mStates);
00209         mBasis.push_back(SubWidgetInfo(_bind.mType, _bind.mOffset, _bind.mAlign));
00210         checkBasis();
00211         fillState(_bind.mStates, mBasis.size()-1);
00212     }
00213 
00214     void ResourceSkin::addProperty(const std::string &_key, const std::string &_value)
00215     {
00216         mProperties[_key] = _value;
00217     }
00218 
00219     void ResourceSkin::addChild(const ChildSkinInfo& _child)
00220     {
00221         mChilds.push_back(_child);
00222     }
00223 
00224     bool ResourceSkin::loadMask(const std::string& _file)
00225     {
00226         return mMaskPeek.load(_file);
00227     }
00228 
00229     void ResourceSkin::clear()
00230     {
00231         for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter!=mStates.end(); ++iter)
00232         {
00233             for (VectorStateInfo::iterator iter2=iter->second.begin(); iter2!=iter->second.end(); ++iter2)
00234             {
00235                 delete *iter2;
00236             }
00237         }
00238     }
00239 
00240     void ResourceSkin::checkState(const MapStateInfo& _states)
00241     {
00242         for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
00243         {
00244             checkState(iter->first);
00245         }
00246     }
00247 
00248     void ResourceSkin::checkState(const std::string& _name)
00249     {
00250         // ищем такой же ключ
00251         MapWidgetStateInfo::const_iterator iter = mStates.find(_name);
00252         if (iter == mStates.end())
00253         {
00254             // добавляем новый стейт
00255             mStates[_name] = VectorStateInfo();
00256         }
00257     }
00258 
00259     void ResourceSkin::checkBasis()
00260     {
00261         // и увеличиваем размер смещений по колличеству сабвиджетов
00262         for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter!=mStates.end(); ++iter)
00263         {
00264             iter->second.resize(mBasis.size());
00265         }
00266     }
00267 
00268     void ResourceSkin::fillState(const MapStateInfo& _states, size_t _index)
00269     {
00270         for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
00271         {
00272             mStates[iter->first][_index] = iter->second;
00273         }
00274     }
00275 
00276 } // namespace MyGUI