MyGUI
3.2.0
|
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