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