MyGUI  3.2.0
MyGUI_BiIndexBase.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_BiIndexBase.h"
00024 
00025 namespace MyGUI
00026 {
00027 
00028     BiIndexBase::BiIndexBase()
00029     {
00030     }
00031 
00032     BiIndexBase::~BiIndexBase()
00033     {
00034     }
00035 
00036     size_t BiIndexBase::getIndexCount() const
00037     {
00038         return mIndexFace.size();
00039     }
00040 
00041     size_t BiIndexBase::insertItemAt(size_t _index)
00042     {
00043         #if MYGUI_DEBUG_MODE == 1
00044             MYGUI_ASSERT_RANGE_INSERT(_index, mIndexFace.size(), "BiIndexBase::insertItemAt");
00045             checkIndexes();
00046         #endif
00047 
00048         if (_index == MyGUI::ITEM_NONE)
00049             _index = mIndexFace.size();
00050 
00051         size_t index;
00052 
00053         if (_index == mIndexFace.size())
00054         {
00055             // для вставки айтема
00056             index = mIndexFace.size();
00057 
00058             mIndexFace.push_back(_index);
00059             mIndexBack.push_back(_index);
00060         }
00061         else
00062         {
00063             // для вставки айтема
00064             index = mIndexFace[_index];
00065 
00066             size_t count = mIndexFace.size();
00067             for (size_t pos = 0; pos < count; ++pos)
00068             {
00069                 if (mIndexFace[pos] >= index)
00070                     mIndexFace[pos]++;
00071             }
00072             mIndexFace.insert(mIndexFace.begin() + _index, index);
00073 
00074             count ++;
00075             mIndexBack.push_back(0);
00076             for (size_t pos = 0; pos < count; ++pos)
00077             {
00078                 mIndexBack[mIndexFace[pos]] = pos;
00079             }
00080         }
00081 
00082         #if MYGUI_DEBUG_MODE == 1
00083             checkIndexes();
00084         #endif
00085 
00086         return index;
00087     }
00088 
00089     size_t BiIndexBase::removeItemAt(size_t _index)
00090     {
00091         #if MYGUI_DEBUG_MODE == 1
00092             MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt");
00093             checkIndexes();
00094         #endif
00095 
00096         // для удаления айтема
00097         size_t index = mIndexFace[_index];
00098 
00099         mIndexFace.erase(mIndexFace.begin() + _index);
00100         mIndexBack.pop_back();
00101 
00102         size_t count = mIndexFace.size();
00103         for (size_t pos = 0; pos < count; ++pos)
00104         {
00105             if (mIndexFace[pos] > index)
00106                 mIndexFace[pos]--;
00107             mIndexBack[mIndexFace[pos]] = pos;
00108         }
00109 
00110         #if MYGUI_DEBUG_MODE == 1
00111             checkIndexes();
00112         #endif
00113 
00114         return index;
00115     }
00116 
00117     void BiIndexBase::removeAllItems()
00118     {
00119         mIndexFace.clear();
00120         mIndexBack.clear();
00121     }
00122 
00123     // на входе индексы пользователя, на выходе реальные индексы
00124     size_t BiIndexBase::convertToBack(size_t _index) const
00125     {
00126         #if MYGUI_DEBUG_MODE == 1
00127             MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToBack");
00128         #endif
00129         return _index == ITEM_NONE ? ITEM_NONE : mIndexFace[_index];
00130     }
00131 
00132     // на входе индексы реальные, на выходе, то что видит пользователь
00133     size_t BiIndexBase::convertToFace(size_t _index) const
00134     {
00135         #if MYGUI_DEBUG_MODE == 1
00136             MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToFace");
00137         #endif
00138         return _index == ITEM_NONE ? ITEM_NONE : mIndexBack[_index];
00139     }
00140 
00141     // меняет местами два индекса, индексы со стороны пользователя
00142     void BiIndexBase::swapItemsFaceAt(size_t _index1, size_t _index2)
00143     {
00144         #if MYGUI_DEBUG_MODE == 1
00145             MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
00146             MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
00147         #endif
00148 
00149         std::swap(mIndexFace[_index1], mIndexFace[_index2]);
00150         std::swap(mIndexBack[mIndexFace[_index1]], mIndexBack[mIndexFace[_index2]]);
00151     }
00152 
00153     // меняет местами два индекса, индексы со сторонны данных
00154     void BiIndexBase::swapItemsBackAt(size_t _index1, size_t _index2)
00155     {
00156         #if MYGUI_DEBUG_MODE == 1
00157             MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
00158             MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
00159         #endif
00160 
00161         std::swap(mIndexBack[_index1], mIndexBack[_index2]);
00162         std::swap(mIndexFace[mIndexBack[_index1]], mIndexFace[mIndexBack[_index2]]);
00163     }
00164 
00165     #if MYGUI_DEBUG_MODE == 1
00166 
00167     void BiIndexBase::checkIndexes()
00168     {
00169         assert(mIndexFace.size() == mIndexBack.size());
00170 
00171         // проверяем на уникальность каждого индекса в маппинге
00172         std::vector<bool> vec;
00173         size_t count = mIndexFace.size();
00174 
00175         vec.reserve(count);
00176         for (size_t pos = 0; pos < count; ++pos)
00177             vec.push_back(false);
00178 
00179         for (size_t pos = 0; pos < count; ++pos)
00180         {
00181             // максимум
00182             size_t index = mIndexBack[pos];
00183             if (index >= count)
00184                 throw new std::exception();
00185 
00186             // максимум
00187             index = mIndexFace[pos];
00188             if (index >= count)
00189                 throw new std::exception();
00190 
00191             if (vec[index])
00192                 throw new std::exception();
00193             vec[index] = true;
00194         }
00195 
00196         for (size_t pos = 0; pos < count; ++pos)
00197         {
00198             if (!vec[pos])
00199                 throw new std::exception();
00200         }
00201 
00202         // проверяем на взаимоссылаемость индексов
00203         for (size_t pos = 0; pos < count; ++pos)
00204         {
00205             size_t index = mIndexFace[pos];
00206             if (mIndexBack[index] != pos)
00207                 throw new std::exception();
00208         }
00209     }
00210 
00211 #endif
00212 
00213 } // namespace MyGUI