MyGUI  3.2.0
MyGUI_ResourceSkin.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_ResourceSkin.h"
00024 #include "MyGUI_FactoryManager.h"
00025 #include "MyGUI_LanguageManager.h"
00026 
00027 namespace MyGUI
00028 {
00029 
00030     ResourceSkin::ResourceSkin()
00031     {
00032     }
00033 
00034     ResourceSkin::~ResourceSkin()
00035     {
00036         for (MapWidgetStateInfo::iterator item = mStates.begin(); item != mStates.end(); ++ item)
00037         {
00038             for (VectorStateInfo::iterator info = (*item).second.begin(); info != (*item).second.end(); ++ info)
00039                 delete (*info);
00040         }
00041         mStates.clear();
00042     }
00043 
00044     void ResourceSkin::deserialization(xml::ElementPtr _node, Version _version)
00045     {
00046         Base::deserialization(_node, _version);
00047 
00048         // парсим атрибуты скина
00049         std::string name, texture, tmp;
00050         IntSize size;
00051         _node->findAttribute("name", name);
00052         _node->findAttribute("texture", texture);
00053         if (_node->findAttribute("size", tmp)) size = IntSize::parse(tmp);
00054 
00055         LanguageManager& localizator = LanguageManager::getInstance();
00056 
00057         // вспомогательный класс для биндинга сабскинов
00058         SubWidgetBinding bind;
00059 
00060         // поддержка замены тегов в скинах
00061         if (_version >= Version(1, 1))
00062         {
00063             texture = localizator.replaceTags(texture);
00064         }
00065 
00066         setInfo(size, texture);
00067 
00068         // проверяем маску
00069         if (_node->findAttribute("mask", tmp))
00070             addProperty("MaskPick", tmp);
00071 
00072         // берем детей и крутимся, цикл с саб скинами
00073         xml::ElementEnumerator basis = _node->getElementEnumerator();
00074         while (basis.next())
00075         {
00076             if (basis->getName() == "Property")
00077             {
00078                 // загружаем свойства
00079                 std::string key, value;
00080                 if (!basis->findAttribute("key", key)) continue;
00081                 if (!basis->findAttribute("value", value)) continue;
00082 
00083                 // поддержка замены тегов в скинах
00084                 if (_version >= Version(1, 1))
00085                 {
00086                     value = localizator.replaceTags(value);
00087                 }
00088 
00089                 // добавляем свойство
00090                 addProperty(key, value);
00091             }
00092             else if (basis->getName() == "Child")
00093             {
00094                 ChildSkinInfo child(
00095                     basis->findAttribute("type"),
00096                     WidgetStyle::parse(basis->findAttribute("style")),
00097                     basis->findAttribute("skin"),
00098                     IntCoord::parse(basis->findAttribute("offset")),
00099                     Align::parse(basis->findAttribute("align")),
00100                     basis->findAttribute("layer"),
00101                     basis->findAttribute("name")
00102                 );
00103 
00104                 xml::ElementEnumerator child_params = basis->getElementEnumerator();
00105                 while (child_params.next("Property"))
00106                     child.addParam(child_params->findAttribute("key"), child_params->findAttribute("value"));
00107 
00108                 addChild(child);
00109                 //continue;
00110             }
00111             else if (basis->getName() == "BasisSkin")
00112             {
00113                 // парсим атрибуты
00114                 std::string basisSkinType, tmp_str;
00115                 IntCoord offset;
00116                 Align align = Align::Default;
00117                 basis->findAttribute("type", basisSkinType);
00118                 if (basis->findAttribute("offset", tmp_str)) offset = IntCoord::parse(tmp_str);
00119                 if (basis->findAttribute("align", tmp_str)) align = Align::parse(tmp_str);
00120 
00121                 bind.create(offset, align, basisSkinType);
00122 
00123                 // берем детей и крутимся, цикл со стейтами
00124                 xml::ElementEnumerator state = basis->getElementEnumerator();
00125 
00126                 // проверяем на новый формат стейтов
00127                 bool new_format = false;
00128                 // если версия меньше 1.0 то переименовываем стейты
00129                 if (_version < Version(1, 0))
00130                 {
00131                     while (state.next())
00132                     {
00133                         if (state->getName() == "State")
00134                         {
00135                             const std::string& name_state = state->findAttribute("name");
00136                             if ((name_state == "normal_checked") || (state->findAttribute("name") == "normal_check"))
00137                             {
00138                                 new_format = true;
00139                                 break;
00140                             }
00141                         }
00142                     }
00143                     // обновляем
00144                     state = basis->getElementEnumerator();
00145                 }
00146 
00147                 while (state.next())
00148                 {
00149                     if (state->getName() == "State")
00150                     {
00151                         // парсим атрибуты стейта
00152                         std::string basisStateName;
00153                         state->findAttribute("name", basisStateName);
00154 
00155                         // если версия меньше 1.0 то переименовываем стейты
00156                         if (_version < Version(1, 0))
00157                         {
00158                             // это обсолет новых типов
00159                             if (basisStateName == "disable_check") basisStateName = "disabled_checked";
00160                             else if (basisStateName == "normal_check") basisStateName = "normal_checked";
00161                             else if (basisStateName == "active_check") basisStateName = "highlighted_checked";
00162                             else if (basisStateName == "pressed_check") basisStateName = "pushed_checked";
00163                             else if (basisStateName == "disable") basisStateName = "disabled";
00164                             else if (basisStateName == "active") basisStateName = "highlighted";
00165                             else if (basisStateName == "select") basisStateName = "pushed";
00166                             else if (basisStateName == "pressed")
00167                             {
00168                                 if (new_format) basisStateName = "pushed";
00169                                 else basisStateName = "normal_checked";
00170                             }
00171                         }
00172 
00173                         // конвертируем инфу о стейте
00174                         IStateInfo* data = nullptr;
00175                         IObject* object = FactoryManager::getInstance().createObject("BasisSkin/State", 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