1 /* 2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 3 * Distributed under the MIT License 4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 5 */ 6 7 #include "MyGUI_Precompiled.h" 8 #include "MyGUI_BiIndexBase.h" 9 10 namespace MyGUI 11 { 12 getIndexCount() const13 size_t BiIndexBase::getIndexCount() const 14 { 15 return mIndexFace.size(); 16 } 17 insertItemAt(size_t _index)18 size_t BiIndexBase::insertItemAt(size_t _index) 19 { 20 #if MYGUI_DEBUG_MODE == 1 21 MYGUI_ASSERT_RANGE_INSERT(_index, mIndexFace.size(), "BiIndexBase::insertItemAt"); 22 checkIndexes(); 23 #endif 24 25 if (_index == MyGUI::ITEM_NONE) 26 _index = mIndexFace.size(); 27 28 size_t index; 29 30 if (_index == mIndexFace.size()) 31 { 32 // для вставки айтема 33 index = mIndexFace.size(); 34 35 mIndexFace.push_back(_index); 36 mIndexBack.push_back(_index); 37 } 38 else 39 { 40 // для вставки айтема 41 index = mIndexFace[_index]; 42 43 size_t count = mIndexFace.size(); 44 for (size_t pos = 0; pos < count; ++pos) 45 { 46 if (mIndexFace[pos] >= index) 47 mIndexFace[pos]++; 48 } 49 mIndexFace.insert(mIndexFace.begin() + _index, index); 50 51 count ++; 52 mIndexBack.push_back(0); 53 for (size_t pos = 0; pos < count; ++pos) 54 { 55 mIndexBack[mIndexFace[pos]] = pos; 56 } 57 } 58 59 #if MYGUI_DEBUG_MODE == 1 60 checkIndexes(); 61 #endif 62 63 return index; 64 } 65 removeItemAt(size_t _index)66 size_t BiIndexBase::removeItemAt(size_t _index) 67 { 68 #if MYGUI_DEBUG_MODE == 1 69 MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt"); 70 checkIndexes(); 71 #endif 72 73 // для удаления айтема 74 size_t index = mIndexFace[_index]; 75 76 mIndexFace.erase(mIndexFace.begin() + _index); 77 mIndexBack.pop_back(); 78 79 size_t count = mIndexFace.size(); 80 for (size_t pos = 0; pos < count; ++pos) 81 { 82 if (mIndexFace[pos] > index) 83 mIndexFace[pos]--; 84 mIndexBack[mIndexFace[pos]] = pos; 85 } 86 87 #if MYGUI_DEBUG_MODE == 1 88 checkIndexes(); 89 #endif 90 91 return index; 92 } 93 removeAllItems()94 void BiIndexBase::removeAllItems() 95 { 96 mIndexFace.clear(); 97 mIndexBack.clear(); 98 } 99 100 // на входе индексы пользователя, на выходе реальные индексы convertToBack(size_t _index) const101 size_t BiIndexBase::convertToBack(size_t _index) const 102 { 103 #if MYGUI_DEBUG_MODE == 1 104 MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToBack"); 105 #endif 106 return _index == ITEM_NONE ? ITEM_NONE : mIndexFace[_index]; 107 } 108 109 // на входе индексы реальные, на выходе, то что видит пользователь convertToFace(size_t _index) const110 size_t BiIndexBase::convertToFace(size_t _index) const 111 { 112 #if MYGUI_DEBUG_MODE == 1 113 MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToFace"); 114 #endif 115 return _index == ITEM_NONE ? ITEM_NONE : mIndexBack[_index]; 116 } 117 118 // меняет местами два индекса, индексы со стороны пользователя swapItemsFaceAt(size_t _index1,size_t _index2)119 void BiIndexBase::swapItemsFaceAt(size_t _index1, size_t _index2) 120 { 121 #if MYGUI_DEBUG_MODE == 1 122 MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt"); 123 MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt"); 124 #endif 125 126 std::swap(mIndexFace[_index1], mIndexFace[_index2]); 127 std::swap(mIndexBack[mIndexFace[_index1]], mIndexBack[mIndexFace[_index2]]); 128 } 129 130 // меняет местами два индекса, индексы со сторонны данных swapItemsBackAt(size_t _index1,size_t _index2)131 void BiIndexBase::swapItemsBackAt(size_t _index1, size_t _index2) 132 { 133 #if MYGUI_DEBUG_MODE == 1 134 MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsBackAt"); 135 MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsBackAt"); 136 #endif 137 138 std::swap(mIndexBack[_index1], mIndexBack[_index2]); 139 std::swap(mIndexFace[mIndexBack[_index1]], mIndexFace[mIndexBack[_index2]]); 140 } 141 142 #if MYGUI_DEBUG_MODE == 1 143 checkIndexes()144 void BiIndexBase::checkIndexes() 145 { 146 assert(mIndexFace.size() == mIndexBack.size()); 147 148 // проверяем на уникальность каждого индекса в маппинге 149 std::vector<bool> vec; 150 size_t count = mIndexFace.size(); 151 152 vec.reserve(count); 153 for (size_t pos = 0; pos < count; ++pos) 154 vec.push_back(false); 155 156 for (size_t pos = 0; pos < count; ++pos) 157 { 158 // максимум 159 size_t index = mIndexBack[pos]; 160 if (index >= count) 161 throw new std::exception(); 162 163 // максимум 164 index = mIndexFace[pos]; 165 if (index >= count) 166 throw new std::exception(); 167 168 if (vec[index]) 169 throw new std::exception(); 170 vec[index] = true; 171 } 172 173 for (size_t pos = 0; pos < count; ++pos) 174 { 175 if (!vec[pos]) 176 throw new std::exception(); 177 } 178 179 // проверяем на взаимоссылаемость индексов 180 for (size_t pos = 0; pos < count; ++pos) 181 { 182 size_t index = mIndexFace[pos]; 183 if (mIndexBack[index] != pos) 184 throw new std::exception(); 185 } 186 } 187 188 #endif 189 190 } // namespace MyGUI 191