MyGUI
3.0.1
|
00001 00007 /* 00008 This file is part of MyGUI. 00009 00010 MyGUI is free software: you can redistribute it and/or modify 00011 it under the terms of the GNU Lesser General Public License as published by 00012 the Free Software Foundation, either version 3 of the License, or 00013 (at your option) any later version. 00014 00015 MyGUI is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU Lesser General Public License for more details. 00019 00020 You should have received a copy of the GNU Lesser General Public License 00021 along with MyGUI. If not, see <http://www.gnu.org/licenses/>. 00022 */ 00023 #ifndef __MYGUI_BIINDEX_BASE_H__ 00024 #define __MYGUI_BIINDEX_BASE_H__ 00025 00026 #include "MyGUI_Prerequest.h" 00027 00028 namespace MyGUI 00029 { 00030 00031 class BiIndexBase 00032 { 00033 public: 00034 virtual ~BiIndexBase() { } 00035 protected: 00036 00037 size_t getIndexCount() { return mIndexFace.size(); } 00038 00039 size_t insertItemAt(size_t _index) 00040 { 00041 #if MYGUI_DEBUG_MODE == 1 00042 MYGUI_ASSERT_RANGE_INSERT(_index, mIndexFace.size(), "BiIndexBase::insertItemAt"); 00043 checkIndexes(); 00044 #endif 00045 00046 if (_index == MyGUI::ITEM_NONE) _index = mIndexFace.size(); 00047 00048 size_t index; 00049 00050 if (_index == mIndexFace.size()) 00051 { 00052 // для вставки айтема 00053 index = mIndexFace.size(); 00054 00055 mIndexFace.push_back(_index); 00056 mIndexBack.push_back(_index); 00057 } 00058 else 00059 { 00060 // для вставки айтема 00061 index = mIndexFace[_index]; 00062 00063 size_t count = mIndexFace.size(); 00064 for (size_t pos=0; pos<count; ++pos) 00065 { 00066 if (mIndexFace[pos] >= index) mIndexFace[pos]++; 00067 } 00068 mIndexFace.insert(mIndexFace.begin() + _index, index); 00069 00070 count ++; 00071 mIndexBack.push_back(0); 00072 for (size_t pos=0; pos<count; ++pos) 00073 { 00074 mIndexBack[mIndexFace[pos]] = pos; 00075 } 00076 } 00077 00078 #if MYGUI_DEBUG_MODE == 1 00079 checkIndexes(); 00080 #endif 00081 00082 return index; 00083 } 00084 00085 size_t removeItemAt(size_t _index) 00086 { 00087 #if MYGUI_DEBUG_MODE == 1 00088 MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt"); 00089 checkIndexes(); 00090 #endif 00091 00092 // для удаления айтема 00093 size_t index = mIndexFace[_index]; 00094 00095 mIndexFace.erase(mIndexFace.begin() + _index); 00096 mIndexBack.pop_back(); 00097 00098 size_t count = mIndexFace.size(); 00099 for (size_t pos=0; pos<count; ++pos) 00100 { 00101 if (mIndexFace[pos] > index) mIndexFace[pos]--; 00102 mIndexBack[mIndexFace[pos]] = pos; 00103 } 00104 00105 #if MYGUI_DEBUG_MODE == 1 00106 checkIndexes(); 00107 #endif 00108 00109 return index; 00110 } 00111 00112 void removeAllItems() 00113 { 00114 mIndexFace.clear(); 00115 mIndexBack.clear(); 00116 } 00117 00118 // на входе индексы пользователя, на выходе реальные индексы 00119 size_t convertToBack(size_t _index) const 00120 { 00121 #if MYGUI_DEBUG_MODE == 1 00122 MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToBack"); 00123 #endif 00124 return _index == ITEM_NONE ? ITEM_NONE : mIndexFace[_index]; 00125 } 00126 00127 // на входе индексы реальные, на выходе, то что видит пользователь 00128 size_t convertToFace(size_t _index) const 00129 { 00130 #if MYGUI_DEBUG_MODE == 1 00131 MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToFace"); 00132 #endif 00133 return _index == ITEM_NONE ? ITEM_NONE : mIndexBack[_index]; 00134 } 00135 00136 // меняет местами два индекса, индексы со стороны пользователя 00137 void swapItemsFaceAt(size_t _index1, size_t _index2) 00138 { 00139 #if MYGUI_DEBUG_MODE == 1 00140 MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt"); 00141 MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt"); 00142 #endif 00143 00144 std::swap(mIndexFace[_index1], mIndexFace[_index2]); 00145 std::swap(mIndexBack[mIndexFace[_index1]], mIndexBack[mIndexFace[_index2]]); 00146 } 00147 00148 // меняет местами два индекса, индексы со сторонны данных 00149 void swapItemsBackAt(size_t _index1, size_t _index2) 00150 { 00151 #if MYGUI_DEBUG_MODE == 1 00152 MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsBackAt"); 00153 MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsBackAt"); 00154 #endif 00155 00156 std::swap(mIndexBack[_index1], mIndexBack[_index2]); 00157 std::swap(mIndexFace[mIndexBack[_index1]], mIndexFace[mIndexBack[_index2]]); 00158 } 00159 00160 #if MYGUI_DEBUG_MODE == 1 00161 00162 void checkIndexes() 00163 { 00164 assert(mIndexFace.size() == mIndexBack.size()); 00165 00166 // проверяем на уникальность каждого индекса в маппинге 00167 std::vector<bool> vec; 00168 size_t count = mIndexFace.size(); 00169 00170 vec.reserve(count); 00171 for (size_t pos=0; pos<count; ++pos) vec.push_back(false); 00172 00173 for (size_t pos=0; pos<count; ++pos) 00174 { 00175 // максимум 00176 size_t index = mIndexBack[pos]; 00177 if (index >= count) throw new std::exception(); 00178 00179 // максимум 00180 index = mIndexFace[pos]; 00181 if (index >= count) throw new std::exception(); 00182 00183 if (vec[index]) throw new std::exception(); 00184 vec[index] = true; 00185 } 00186 00187 for (size_t pos=0; pos<count; ++pos) 00188 { 00189 if (!vec[pos]) throw new std::exception(); 00190 } 00191 00192 // проверяем на взаимоссылаемость индексов 00193 for (size_t pos=0; pos<count; ++pos) 00194 { 00195 size_t index = mIndexFace[pos]; 00196 if (mIndexBack[index] != pos) throw new std::exception(); 00197 } 00198 } 00199 00200 #endif 00201 00202 private: 00203 typedef std::vector<size_t> VectorSizeT; 00204 00205 // маппинг с индексов, которые видны наружу 00206 // на индексы которые реально используются данными 00207 VectorSizeT mIndexFace; 00208 00209 // маппинг с индексов, которые используют данные 00210 // на индексы которые виндны наружу 00211 VectorSizeT mIndexBack; 00212 }; 00213 00214 } // namespace MyGUI 00215 00216 #endif // __MYGUI_BIINDEX_BASE_H__