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