soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SListViewItemLocator.cpp
1#include "souistd.h"
2#include "helper/SListViewItemLocator.h"
3
4#pragma warning(push)
5#pragma warning(disable : 4985) // disable the warning message during the include
6#include <math.h> // this is where I would normally get the warning message
7#pragma warning(pop)
8
9SNSBEGIN
10//////////////////////////////////////////////////////////////////////////
11// SListViewItemLocatorFix
13 : m_nItemHeight(nItemHei)
14 , m_nDividerSize(nDividerSize)
15 , m_nScale(100)
16{
17}
18
23
25{
26 m_nScale = nScale;
27}
28
30{
31 return m_nDividerSize.toPixelSize(m_nScale);
32}
33
35{
36 return m_nItemHeight.toPixelSize(m_nScale) + m_nDividerSize.toPixelSize(m_nScale);
37}
38
40{
41 if (!m_adapter)
42 return -1;
43 int nRet = position / GetFixItemHeight();
44
45 if (nRet < 0)
46 nRet = 0;
47 if (nRet > m_adapter->getCount())
48 nRet = m_adapter->getCount();
49 return nRet;
50}
51
53{
54 return iItem * GetFixItemHeight();
55}
56
58{
59 if (!m_adapter || m_adapter->getCount() == 0)
60 return 0;
61 return GetFixItemHeight() * m_adapter->getCount() - GetDividerSize();
62}
63
64void SListViewItemLocatorFix::SetItemHeight(int iItem, int nHeight)
65{
66}
67
69{
70 return m_nItemHeight.toPixelSize(m_nScale);
71}
72
74{
75 return TRUE;
76}
77
78void SListViewItemLocatorFix::SetAdapter(ILvAdapter *pAdapter)
79{
80 m_adapter = pAdapter;
81}
82
83//////////////////////////////////////////////////////////////////////////
84// SListViewItemLocatorFlex
85double logbase(double a, double base)
86{
87 return log(a) / log(base);
88}
89
90#define SEGMENT_SIZE 50 //数据分组最大长度
91#define INDEX_WIDTH 10 //索引表一级最大节点数
92
94 : m_nItemHeight(nItemHei)
95 , m_nDividerSize(nDividerSize)
96 , m_nScale(100)
97{
98}
99
104
106{
107 m_nScale = nScale;
109}
110
115
117{
118 return m_nDividerSize.toPixelSize(m_nScale);
119}
120
122{
123 if (!m_adapter)
124 return -1;
125 if (position < 0 || position >= GetTotalHeight())
126 return -1;
127 HSTREEITEM hItem = Offset2Branch(STVI_ROOT, position);
128 SASSERT(hItem);
129 int idx = Branch2Index(hItem);
130 int offset = Branch2Offset(hItem);
131 BranchInfo &bi = m_itemPosIndex.GetItemRef(hItem);
132 (void)bi;
133 SASSERT(bi.nBranchHei >= position - offset);
134
135 int iSeg = idx / SEGMENT_SIZE;
136 int nRemain = position - offset;
137
138 SegmentInfo *psi = m_segments[iSeg];
139
140 for (int i = 0; i < psi->nItems; i++)
141 {
142 int nItemHei = psi->pItemHeight[i] == -1 ? GetFixItemHeight() : psi->pItemHeight[i];
143 if (nRemain <= nItemHei)
144 return idx + i;
145 nRemain -= nItemHei;
146 }
147
148 SASSERT(FALSE);
149 return -1;
150}
151
153{
154 if (!m_adapter)
155 return 0;
156 int iSeg = iItem / SEGMENT_SIZE;
157 int iSubItem = iItem % SEGMENT_SIZE;
158 SegmentInfo *psi = m_segments[iSeg];
159
160 int nPos = Branch2Offset(psi->hItem);
161 for (int i = 0; i < iSubItem; i++)
162 {
163 nPos += psi->pItemHeight[i] == -1 ? GetFixItemHeight() : psi->pItemHeight[i];
164 }
165 return nPos;
166}
167
169{
170 if (!m_adapter)
171 return 0;
172 HSTREEITEM hItem = m_itemPosIndex.GetRootItem();
173 int nRet = m_itemPosIndex.GetItem(hItem).nBranchHei;
174 if (m_adapter->getCount() > 0)
175 nRet -= GetDividerSize();
176 return nRet;
177}
178
179void SListViewItemLocatorFlex::SetItemHeight(int iItem, int nHeight)
180{
181 if (!m_adapter)
182 return;
183
184 int iSeg = iItem / SEGMENT_SIZE;
185 int iSubItem = iItem % SEGMENT_SIZE;
186 SegmentInfo *psi = m_segments[iSeg];
187 int nOldHei = psi->pItemHeight[iSubItem];
188 if (nOldHei == -1)
189 nOldHei = GetFixItemHeight();
190
191 nHeight += GetDividerSize();
192 psi->pItemHeight[iSubItem] = nHeight;
193 if (nOldHei != nHeight)
194 {
195 int nHeiDif = nHeight - nOldHei;
196 HSTREEITEM hBranch = psi->hItem;
197 while (hBranch)
198 {
199 BranchInfo &bi = m_itemPosIndex.GetItemRef(hBranch);
200 bi.nBranchHei += nHeiDif;
201 hBranch = m_itemPosIndex.GetParentItem(hBranch);
202 }
203 }
204}
205
207{
208 if (!m_adapter)
209 return 0;
210 int iSeg = iItem / SEGMENT_SIZE;
211 int iSubItem = iItem % SEGMENT_SIZE;
212 SegmentInfo *psi = m_segments[iSeg];
213 int nRet = psi->pItemHeight[iSubItem];
214 if (nRet == -1)
215 nRet = GetFixItemHeight();
216 nRet -= GetDividerSize();
217 return nRet;
218}
219
221{
222 return FALSE;
223}
224
225void SListViewItemLocatorFlex::SetAdapter(ILvAdapter *pAdapter)
226{
227 m_adapter = pAdapter;
229}
230
232{
233 Clear();
234 if (m_adapter)
235 {
236 int nTreeSize = m_adapter->getCount();
237 int nBranchSize = SEGMENT_SIZE;
238 int nTreeDeep = GetIndexDeep();
239 for (int i = 0; i < nTreeDeep; i++)
240 nBranchSize *= INDEX_WIDTH;
241 InitIndex(STVI_ROOT, nTreeSize, nBranchSize);
242 }
243}
244
245void SListViewItemLocatorFlex::InitIndex(HSTREEITEM hParent, int nItems, int nBranchSize)
246{
247 BranchInfo bi;
248 bi.nBranchHei = nItems * GetFixItemHeight();
249 bi.nBranchSize = nItems;
250
251 HSTREEITEM hBranch = m_itemPosIndex.InsertItem(bi, hParent);
252 if (nItems > SEGMENT_SIZE)
253 { //插入子节点
254 int nRemain = nItems;
255 int nSubBranchSize = nBranchSize / INDEX_WIDTH;
256 while (nRemain > 0)
257 {
258 int nItems2 = nSubBranchSize;
259 if (nItems2 > nRemain)
260 nItems2 = nRemain;
261 InitIndex(hBranch, nItems2, nSubBranchSize);
262 nRemain -= nItems2;
263 }
264 }
265 else
266 {
267 m_segments.Add(new SegmentInfo(nItems, hBranch));
268 }
269}
270
272{
273 return m_nItemHeight.toPixelSize(m_nScale) + m_nDividerSize.toPixelSize(m_nScale);
274}
275
277{
278 if (!m_adapter)
279 return 0;
280 if (m_adapter->getCount() == 0)
281 return 0;
282 return (int)ceil(logbase((m_adapter->getCount() + SEGMENT_SIZE - 1) / SEGMENT_SIZE, INDEX_WIDTH));
283}
284
286{
287 m_itemPosIndex.DeleteAllItems();
288 for (int i = 0; i < (int)m_segments.GetCount(); i++)
289 {
290 delete m_segments[i];
291 }
292 m_segments.RemoveAll();
293}
294
295int SListViewItemLocatorFlex::Branch2Offset(HSTREEITEM hBranch) const
296{
297 int nOffset = 0;
298 HSTREEITEM hPrev = m_itemPosIndex.GetPrevSiblingItem(hBranch);
299 while (hPrev)
300 {
301 nOffset += m_itemPosIndex.GetItem(hPrev).nBranchHei;
302 hPrev = m_itemPosIndex.GetPrevSiblingItem(hPrev);
303 }
304 HSTREEITEM hParent = m_itemPosIndex.GetParentItem(hBranch);
305 if (hParent)
306 {
307 nOffset += Branch2Offset(hParent);
308 }
309 return nOffset;
310}
311
312int SListViewItemLocatorFlex::Branch2Index(HSTREEITEM hBranch) const
313{
314 int iIndex = 0;
315 HSTREEITEM hPrev = m_itemPosIndex.GetPrevSiblingItem(hBranch);
316 while (hPrev)
317 {
318 iIndex += m_itemPosIndex.GetItem(hPrev).nBranchSize;
319 hPrev = m_itemPosIndex.GetPrevSiblingItem(hPrev);
320 }
321 HSTREEITEM hParent = m_itemPosIndex.GetParentItem(hBranch);
322 if (hParent)
323 {
324 iIndex += Branch2Index(hParent);
325 }
326 return iIndex;
327}
328
329HSTREEITEM SListViewItemLocatorFlex::Offset2Branch(HSTREEITEM hParent, int nOffset)
330{
331 HSTREEITEM hItem = m_itemPosIndex.GetChildItem(hParent);
332 if (!hItem)
333 return hParent;
334
335 while (hItem)
336 {
337 BranchInfo bi = m_itemPosIndex.GetItem(hItem);
338 if (nOffset > bi.nBranchHei)
339 {
340 nOffset -= bi.nBranchHei;
341 hItem = m_itemPosIndex.GetNextSiblingItem(hItem);
342 }
343 else
344 {
345 return Offset2Branch(hItem, nOffset);
346 }
347 }
348 return 0;
349}
350SNSEND
#define STVI_ROOT
Definition STree.h:43
布局大小类
Definition SLayoutSize.h:10
void SetScale(int nScale) OVERRIDE
设置缩放比例
int Position2Item(int position) OVERRIDE
将位置转换为项索引
int Item2Position(int iItem) OVERRIDE
将项索引转换为位置
SListViewItemLocatorFix(SLayoutSize nItemHei, SLayoutSize nDividerSize=SLayoutSize())
构造函数
int GetTotalHeight() OVERRIDE
获取总高度
SAutoRefPtr< ILvAdapter > m_adapter
列表适配器对象指针
int GetDividerSize() SCONST OVERRIDE
获取分隔符大小
void SetAdapter(ILvAdapter *pAdapter) OVERRIDE
设置适配器
int GetScrollLineSize() SCONST OVERRIDE
获取滚动行大小
int GetItemHeight(int iItem) SCONST OVERRIDE
获取指定项的高度
BOOL IsFixHeight() SCONST OVERRIDE
检查是否为固定高度
SLayoutSize m_nDividerSize
分隔符的高度
void SetItemHeight(int iItem, int nHeight) OVERRIDE
设置指定项的高度
int GetFixItemHeight() const
获取固定项的高度
SLayoutSize m_nItemHeight
每个项的高度
int * pItemHeight
段中每一个项的高度
int GetDividerSize() SCONST OVERRIDE
获取分隔符大小
SAutoRefPtr< ILvAdapter > m_adapter
列表适配器对象指针
void SetAdapter(ILvAdapter *pAdapter) OVERRIDE
设置适配器
SListViewItemLocatorFlex(SLayoutSize nItemHei, SLayoutSize nDividerSize=SLayoutSize())
构造函数
void InitIndex(HSTREEITEM hParent, int nItems, int nSubBranchSize)
初始化索引
int Position2Item(int position) OVERRIDE
将位置转换为项索引
int GetIndexDeep() const
获取索引深度
BOOL IsFixHeight() SCONST OVERRIDE
检查是否为固定高度
SLayoutSize m_nItemHeight
每个项的高度
int Item2Position(int iItem) OVERRIDE
将项索引转换为位置
int GetTotalHeight() OVERRIDE
获取总高度
int Branch2Offset(HSTREEITEM hBranch) const
将分支转换为偏移量
void OnDataSetChanged() OVERRIDE
数据集发生变化时调用
int GetFixItemHeight() const
获取固定项的高度
HSTREEITEM Offset2Branch(HSTREEITEM hParent, int nOffset)
将偏移量转换为分支
SArray< SegmentInfo * > m_segments
段信息数组
void SetItemHeight(int iItem, int nHeight) OVERRIDE
设置指定项的高度
SLayoutSize m_nDividerSize
分隔符的高度
void SetScale(int nScale) OVERRIDE
设置缩放比例
int GetScrollLineSize() SCONST OVERRIDE
获取滚动行大小
int Branch2Index(HSTREEITEM hBranch) const
将分支转换为索引
CSTree< BranchInfo > m_itemPosIndex
记录分支高度
int GetItemHeight(int iItem) SCONST OVERRIDE
获取指定项的高度
int nBranchSize
分支中包含的节点数量