MyGUI 3.4.3
MyGUI_BiIndexBase.cpp
Go to the documentation of this file.
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
10namespace MyGUI
11{
12
14 {
15 return mIndexFace.size();
16 }
17
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");
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
61#endif
62
63 return index;
64 }
65
66 size_t BiIndexBase::removeItemAt(size_t _index)
67 {
68#if MYGUI_DEBUG_MODE == 1
69 MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt");
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
89#endif
90
91 return index;
92 }
93
95 {
96 mIndexFace.clear();
97 mIndexBack.clear();
98 }
99
100 // на входе индексы пользователя, на выходе реальные индексы
101 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 // на входе индексы реальные, на выходе, то что видит пользователь
110 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 // меняет местами два индекса, индексы со стороны пользователя
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 // меняет местами два индекса, индексы со сторонны данных
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
143 {
144 assert(mIndexFace.size() == mIndexBack.size());
145
146 // check that index is unique
147 std::vector<bool> vec;
148 size_t count = mIndexFace.size();
149
150 vec.reserve(count);
151 for (size_t pos = 0; pos < count; ++pos)
152 vec.push_back(false);
153
154 for (size_t pos = 0; pos < count; ++pos)
155 {
156 size_t index = mIndexBack[pos];
157 MYGUI_ASSERT(index < count, "Invalid index");
158
159 index = mIndexFace[pos];
160 MYGUI_ASSERT(index < count, "Invalid index");
161
162 MYGUI_ASSERT(!vec[index], "Invalid index");
163 vec[index] = true;
164 }
165
166 // check for index cross-reference
167 for (size_t pos = 0; pos < count; ++pos)
168 {
169 size_t index = mIndexFace[pos];
170 MYGUI_ASSERT(mIndexBack[index] == pos, "Invalid index: cross-reference");
171 }
172 }
173
174} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_ASSERT_RANGE_INSERT(index, size, owner)
#define MYGUI_ASSERT_RANGE(index, size, owner)
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
void swapItemsBackAt(size_t _index1, size_t _index2)
size_t removeItemAt(size_t _index)
size_t insertItemAt(size_t _index)
size_t convertToBack(size_t _index) const
size_t convertToFace(size_t _index) const
size_t getIndexCount() const
void swapItemsFaceAt(size_t _index1, size_t _index2)
constexpr size_t ITEM_NONE