soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
STreeView.cpp
1#include "souistd.h"
2#include "control/STreeView.h"
3
4SNSBEGIN
5class STreeViewDataSetObserver : public TObjRefImpl<ITvDataSetObserver> {
6 public:
7 STreeViewDataSetObserver(STreeView *pView)
8 : m_pOwner(pView)
9 {
10 }
11
12 STDMETHOD_(void, onBranchChanged)(THIS_ HSTREEITEM hBranch) OVERRIDE
13 {
14 m_pOwner->onBranchChanged(hBranch);
15 }
16
17 STDMETHOD_(void, onBranchInvalidated)
18 (THIS_ HSTREEITEM hBranch, BOOL bInvalidParents, BOOL bInvalidChildren) OVERRIDE
19 {
20 m_pOwner->onBranchInvalidated(hBranch, bInvalidParents, bInvalidChildren);
21 }
22
23 STDMETHOD_(void, onBranchExpandedChanged)
24 (THIS_ HSTREEITEM hBranch, BOOL bExpandedOld, BOOL bExpandedNew) OVERRIDE
25 {
26 m_pOwner->onBranchExpandedChanged(hBranch, bExpandedOld, bExpandedNew);
27 }
28
29 STDMETHOD_(void, notifyItemBeforeRemove)(THIS_ HSTREEITEM hItem) OVERRIDE
30 {
31 m_pOwner->onItemBeforeRemove(hItem);
32 }
33
34 protected:
35 STreeView *m_pOwner;
36};
37
38//////////////////////////////////////////////////////////////////////////
40 : m_nLineHeight(50)
41 , m_nIndent(nIndent)
42 , m_szDef(10, 50)
43{
44}
45
49
50void STreeViewItemLocator::SetAdapter(ITvAdapter *pAdapter)
51{
52 m_adapter = pAdapter;
53}
54
56{
57 if (hItem != ITEM_ROOT)
58 {
59 _SetItemHeight(hItem, m_szDef.cy);
60 _SetItemWidth(hItem, m_szDef.cx);
61 }
62 else
63 {
64 _SetItemHeight(hItem, 0);
65 _SetItemWidth(hItem, 0);
66 }
67 if (m_adapter->HasChildren(hItem))
68 { // 有子节点
69 HSTREEITEM hChild = m_adapter->GetFirstChildItem(hItem);
70 int nBranchHeight = 0;
71 while (hChild != ITEM_NULL)
72 {
73 // 设置偏移
74 _SetItemOffset(hChild, nBranchHeight);
75 _InitBranch(hChild);
76 nBranchHeight += _GetItemVisibleHeight(hChild);
77 hChild = m_adapter->GetNextSiblingItem(hChild);
78 }
79 _SetBranchHeight(hItem, nBranchHeight);
80 // 设置默认宽度
82 }
83 else
84 { // 无子节点
85 _SetBranchHeight(hItem, 0);
86 _SetBranchWidth(hItem, 0);
87 }
88}
89
90BOOL STreeViewItemLocator::_IsItemVisible(HSTREEITEM hItem) const
91{
92 return m_adapter->IsItemVisible(hItem);
93}
94
95HSTREEITEM STreeViewItemLocator::_Position2Item(int position, HSTREEITEM hParent, int nParentPosition) const
96{
97 if (position < nParentPosition || position >= (nParentPosition + _GetItemVisibleHeight(hParent)))
98 return ITEM_NULL;
99
100 int nItemHeight = GetItemHeight(hParent);
101 int nPos = nParentPosition + nItemHeight;
102
103 if (nPos > position)
104 return hParent;
105
106 SASSERT(IsItemExpanded(hParent));
107
108 int nParentBranchHeight = _GetBranchHeight(hParent);
109
110 if (position - nPos < nParentBranchHeight / 2)
111 { // 从first开始查找
112 HSTREEITEM hItem = m_adapter->GetFirstChildItem(hParent);
113 while (hItem)
114 {
115 int nBranchHeight = _GetItemVisibleHeight(hItem);
116 if (nPos + nBranchHeight > position)
117 {
118 return _Position2Item(position, hItem, nPos);
119 }
120 nPos += nBranchHeight;
121 hItem = m_adapter->GetNextSiblingItem(hItem);
122 }
123 }
124 else
125 { // 从last开始查找
126 nPos += nParentBranchHeight;
127
128 HSTREEITEM hItem = m_adapter->GetLastChildItem(hParent);
129 while (hItem)
130 {
131 int nBranchHeight = _GetItemVisibleHeight(hItem);
132 nPos -= nBranchHeight;
133 if (nPos <= position)
134 {
135 return _Position2Item(position, hItem, nPos);
136 }
137 hItem = m_adapter->GetPrevSiblingItem(hItem);
138 }
139 }
140
141 SASSERT(FALSE); // 不应该走到这里来
142 return ITEM_NULL;
143}
144
146{
147 int nRet = GetItemWidth(hItem);
148 if (m_adapter->IsItemExpanded(hItem) && m_adapter->GetFirstChildItem(hItem) != ITEM_NULL)
149 { // branch wid includes indent size of its children.
150 nRet = smax(nRet, _GetBranchWidth(hItem));
151 }
152 return nRet;
153}
154
156{
157 int nRet = GetItemHeight(hItem);
158 if (IsItemExpanded(hItem))
159 nRet += _GetBranchHeight(hItem);
160 return nRet;
161}
162
163void STreeViewItemLocator::_SetItemHeight(HSTREEITEM hItem, int nHeight)
164{
165 m_adapter->SetItemDataByIndex(hItem, DATA_INDEX_ITEM_HEIGHT, nHeight);
166}
167
168void STreeViewItemLocator::_SetItemOffset(HSTREEITEM hItem, int nOffset)
169{
170 m_adapter->SetItemDataByIndex(hItem, DATA_INDEX_ITEM_OFFSET, nOffset);
171}
172
173int STreeViewItemLocator::_GetItemOffset(HSTREEITEM hItem) const
174{
175 return (int)m_adapter->GetItemDataByIndex(hItem, DATA_INDEX_ITEM_OFFSET);
176}
177
179{
180 int nOffset = _GetItemOffset(hItem);
181 nOffset += _GetItemVisibleHeight(hItem);
182
183 HSTREEITEM hSib = m_adapter->GetNextSiblingItem(hItem);
184 while (hSib != ITEM_NULL)
185 {
186 _SetItemOffset(hSib, nOffset);
187 nOffset += _GetItemVisibleHeight(hSib);
188 hSib = m_adapter->GetNextSiblingItem(hSib);
189 }
190 // 注意更新各级父节点的偏移量
191 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
192 if (hParent != ITEM_NULL && hParent != ITEM_ROOT && IsItemExpanded(hParent))
193 {
194 _UpdateSiblingsOffset(hParent);
195 }
196}
197
198void STreeViewItemLocator::_UpdateBranchHeight(HSTREEITEM hItem, int nDiff)
199{
200 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
201 while (hParent != ITEM_NULL)
202 {
203 int nBranchHeight = _GetBranchHeight(hParent);
204 _SetBranchHeight(hParent, nBranchHeight + nDiff);
205 hParent = m_adapter->GetParentItem(hParent);
206 }
207}
208
209void STreeViewItemLocator::_SetBranchHeight(HSTREEITEM hItem, int nHeight)
210{
211 m_adapter->SetItemDataByIndex(hItem, DATA_INDEX_BRANCH_HEIGHT, nHeight);
212}
213
214int STreeViewItemLocator::_GetBranchHeight(HSTREEITEM hItem) const
215{
216 return (int)m_adapter->GetItemDataByIndex(hItem, DATA_INDEX_BRANCH_HEIGHT);
217}
218
219void STreeViewItemLocator::_SetItemWidth(HSTREEITEM hItem, int nWidth)
220{
221 m_adapter->SetItemDataByIndex(hItem, DATA_INDEX_ITEM_WIDTH, nWidth);
222}
223
224void STreeViewItemLocator::_SetBranchWidth(HSTREEITEM hBranch, int nWidth)
225{
226 m_adapter->SetItemDataByIndex(hBranch, DATA_INDEX_BRANCH_WIDTH, nWidth);
227}
228
229int STreeViewItemLocator::_GetBranchWidth(HSTREEITEM hBranch) const
230{
231 return (int)m_adapter->GetItemDataByIndex(hBranch, DATA_INDEX_BRANCH_WIDTH);
232}
233
234void STreeViewItemLocator::_UpdateBranchWidth(HSTREEITEM hItem, int nOldWidth, int nNewWidth)
235{
236 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
237 if (hParent == ITEM_NULL)
238 return;
239 int nCurBranchWidth = _GetBranchWidth(hParent);
240
241 int nIndent = hParent == ITEM_ROOT ? 0 : m_nIndent;
242 if (nCurBranchWidth != nOldWidth + nIndent)
243 { // 父节点的宽度不是由当前结点控制的
244 if (nCurBranchWidth < nNewWidth + nIndent)
245 { // 新宽度扩展了父节点的显示宽度
246 _SetBranchWidth(hParent, nNewWidth + nIndent);
247 if (IsItemExpanded(hParent))
248 _UpdateBranchWidth(hParent, nCurBranchWidth, nNewWidth + nIndent);
249 }
250 }
251 else
252 { // 父节点的宽度正好是由hItem的显示宽度
253 int nNewBranchWidth;
254 if (nNewWidth > nOldWidth)
255 {
256 nNewBranchWidth = nNewWidth + nIndent;
257 }
258 else
259 {
260 HSTREEITEM hSib = m_adapter->GetFirstChildItem(hParent);
261 nNewBranchWidth = 0;
262 while (hSib != ITEM_NULL)
263 {
264 nNewBranchWidth = smax(nNewBranchWidth, _GetItemVisibleWidth(hSib));
265 hSib = m_adapter->GetNextSiblingItem(hSib);
266 }
267 nNewBranchWidth += nIndent;
268 }
269 _SetBranchWidth(hParent, nNewBranchWidth);
270 if (IsItemExpanded(hParent))
271 _UpdateBranchWidth(hParent, nCurBranchWidth, nNewBranchWidth);
272 }
273}
274
275BOOL STreeViewItemLocator::IsItemExpanded(HSTREEITEM hItem) const
276{
277 return (BOOL)m_adapter->IsItemExpanded(hItem);
278}
279
280int STreeViewItemLocator::GetItemIndent(HSTREEITEM hItem) const
281{
282 int nRet = 0;
283 for (;;)
284 {
285 hItem = m_adapter->GetParentItem(hItem);
286 if (hItem == ITEM_ROOT)
287 break;
288 nRet += m_nIndent;
289 }
290 return nRet;
291}
292
294{
295 return m_nIndent;
296}
297
299{
300 m_nIndent = nIndent;
301}
302
303int STreeViewItemLocator::GetItemHeight(HSTREEITEM hItem) const
304{
305 return (int)m_adapter->GetItemDataByIndex(hItem, DATA_INDEX_ITEM_HEIGHT);
306}
307
308int STreeViewItemLocator::GetItemWidth(HSTREEITEM hItem) const
309{
310 return (int)m_adapter->GetItemDataByIndex(hItem, DATA_INDEX_ITEM_WIDTH);
311}
312
313void STreeViewItemLocator::SetItemHeight(HSTREEITEM hItem, int nHeight)
314{
315 int nOldHeight = GetItemHeight(hItem);
316 _SetItemHeight(hItem, nHeight);
317 if (nOldHeight != nHeight)
318 {
319 _UpdateBranchHeight(hItem, nHeight - nOldHeight);
321 }
322}
323
324void STreeViewItemLocator::SetItemWidth(HSTREEITEM hItem, int nWidth)
325{
326 int nOldWidth = GetItemWidth(hItem);
327 if (nOldWidth == nWidth)
328 return;
329 int nOldBranchWidth = _GetItemVisibleWidth(hItem);
330 _SetItemWidth(hItem, nWidth);
331 int nNewBranchWidth = _GetItemVisibleWidth(hItem);
332 if (nOldBranchWidth == nNewBranchWidth)
333 return;
334 _UpdateBranchWidth(hItem, nOldBranchWidth, nNewBranchWidth);
335}
336
337HSTREEITEM STreeViewItemLocator::Position2Item(int position) const
338{
339 return _Position2Item(position, ITEM_ROOT, 0);
340}
341
342int STreeViewItemLocator::Item2Position(HSTREEITEM hItem) const
343{
344 if (!_IsItemVisible(hItem))
345 {
346 SASSERT(FALSE);
347 return -1;
348 }
349
350 int nRet = 0;
351 // 获得父节点开始位置
352 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
353 if (hParent != ITEM_NULL && hParent != ITEM_ROOT)
354 {
355 nRet = Item2Position(hParent);
356 // 越过父节点
357 nRet += GetItemHeight(hParent);
358 }
359 // 越过前面兄弟结点
360 nRet += _GetItemOffset(hItem);
361
362 return nRet;
363}
364
369
371{
372 return (int)m_adapter->GetItemDataByIndex(ITEM_ROOT, DATA_INDEX_BRANCH_WIDTH);
373}
374
376{
377 return (int)m_adapter->GetItemDataByIndex(ITEM_ROOT, DATA_INDEX_BRANCH_HEIGHT);
378}
379
380void STreeViewItemLocator::OnBranchExpandedChanged(HSTREEITEM hItem, BOOL bExpandedOld, BOOL bExpandedNew)
381{
382 if (bExpandedNew == bExpandedOld)
383 return;
384 int nOldBranchWidth = _GetBranchWidth(hItem);
385 int nBranchHei = _GetBranchHeight(hItem);
386 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
387 while (hParent != ITEM_NULL)
388 {
389 _SetBranchHeight(hParent, _GetBranchHeight(hParent) + nBranchHei * (bExpandedNew ? 1 : -1));
390 if (!IsItemExpanded(hParent))
391 break;
392 hParent = m_adapter->GetParentItem(hParent);
393 }
395
396 int nNewBranchWidth = _GetItemVisibleWidth(hItem);
397 _UpdateBranchWidth(hItem, nOldBranchWidth, nNewBranchWidth);
398}
399
401{
402 // 初始化列表项高度等数据
403 int nVisibleHeightOld = _GetItemVisibleHeight(hItem);
404 _InitBranch(hItem);
405 int nVisibleHeightNew = _GetItemVisibleHeight(hItem);
406 int nDiff = nVisibleHeightNew - nVisibleHeightOld;
407 if (nDiff == 0 || hItem == ITEM_ROOT)
408 return;
409
410 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
411 while (hParent != ITEM_NULL)
412 {
413 _SetBranchHeight(hParent, _GetBranchHeight(hParent) + nDiff);
414 hParent = m_adapter->GetParentItem(hParent);
415 }
417}
418
419//////////////////////////////////////////////////////////////////////////
421 : m_itemCapture(NULL)
422 , m_pHoverItem(NULL)
423 , m_hSelected(ITEM_NULL)
424 , m_pVisibleMap(new VISIBLEITEMSMAP)
425 , m_bWantTab(FALSE)
426 , m_pLineSkin(GETBUILTINSKIN(SKIN_SYS_TREE_LINES))
427 , m_bHasLines(FALSE)
428 , SHostProxy(this)
429{
430 m_bFocusable = TRUE;
431
432 m_evtSet.addEvent(EVENTID(EventTVSelChanging));
433 m_evtSet.addEvent(EVENTID(EventTVSelChanged));
434 m_observer.Attach(new STreeViewDataSetObserver(this));
436}
437
439{
440 delete m_pVisibleMap;
441}
442
443BOOL STreeView::SetAdapter(ITvAdapter *adapter)
444{
445 if (m_adapter)
446 {
447 m_adapter->unregisterDataSetObserver(m_observer);
448 }
449 if (m_adapter == adapter)
450 {
451 SSLOGW() << "the new adapter is same to previous set adapter, same as onBranchChanged";
452 if (m_adapter)
453 {
454 onBranchChanged(ITEM_ROOT);
455 }
456 return TRUE;
457 }
458 m_adapter = adapter;
459 if (m_adapter)
460 {
461 m_adapter->registerDataSetObserver(m_observer);
462 }
463 {
464 // free all itemPanels in recycle
465 for (size_t i = 0; i < m_itemRecycle.GetCount(); i++)
466 {
467 SList<SItemPanel *> *lstItemPanels = m_itemRecycle.GetAt(i);
468 SPOSITION pos = lstItemPanels->GetHeadPosition();
469 while (pos)
470 {
471 SItemPanel *pItemPanel = lstItemPanels->GetNext(pos);
472 pItemPanel->Destroy();
473 }
474 delete lstItemPanels;
475 }
476 m_itemRecycle.RemoveAll();
477
478 // free all visible itemPanels
479 SPOSITION pos = m_visible_items.GetHeadPosition();
480 while (pos)
481 {
482 ItemInfo ii = m_visible_items.GetNext(pos);
483 ii.pItem->Destroy();
484 }
485 m_visible_items.RemoveAll();
486 m_pVisibleMap->RemoveAll();
487 m_pHoverItem = NULL;
488 m_itemCapture = NULL;
489 m_hSelected = 0;
490 }
491
492 if (m_tvItemLocator)
493 m_tvItemLocator->SetAdapter(adapter);
494
495 if (adapter)
496 {
497 SXmlNode xmlNode = m_xmlTemplate.root().first_child();
498 m_adapter->InitByTemplate(&xmlNode);
499 for (int i = 0; i < m_adapter->getViewTypeCount(); i++)
500 {
501 m_itemRecycle.Add(new SList<SItemPanel *>());
502 }
503 onBranchChanged(ITEM_ROOT);
504 }
505
506 return TRUE;
507}
508
510{
511 SXmlNode xmlTemplate = xmlNode.child(L"template");
512 if (xmlTemplate)
513 {
514 m_xmlTemplate.root().append_copy(xmlTemplate);
515 }
516 return TRUE;
517}
518
520{
521 SPainter painter;
522 BeforePaint(pRT, painter);
523
524 CRect rcClient;
525 GetClientRect(&rcClient);
526 pRT->PushClipRect(&rcClient, RGN_AND);
527
528 CRect rcClip;
529 pRT->GetClipBox(&rcClip);
530 SAutoRefPtr<IRegionS> rgnClip;
531 pRT->GetClipRegion(&rgnClip);
532
533 CPoint pt(0, -1);
534 float fMat[9];
535 pRT->GetTransform(fMat);
536 SMatrix mtx(fMat);
537
538 int nIndent = m_tvItemLocator->GetIndent();
539 for (SPOSITION pos = m_visible_items.GetHeadPosition(); pos;)
540 {
541 ItemInfo ii = m_visible_items.GetNext(pos);
542 HSTREEITEM hItem = (HSTREEITEM)ii.pItem->GetItemIndex();
543 if (pt.y == -1)
544 {
545 pt.y = m_tvItemLocator->Item2Position(hItem) - m_siVer.nPos;
546 }
547 pt.x = -m_siHoz.nPos;
548
549 CSize szItem(m_tvItemLocator->GetItemWidth(hItem), m_tvItemLocator->GetItemHeight(hItem));
550 if (m_bHasLines)
551 {
552 CRect rcItem(pt, CSize(rcClient.Width(), szItem.cy));
553 rcItem.OffsetRect(rcClient.TopLeft());
554 DrawLines(pRT, rcItem, hItem);
555 }
556
557 pt.x = m_tvItemLocator->GetItemIndent(hItem) - m_siHoz.nPos;
558
559 CRect rcItem(pt, szItem);
560 rcItem.OffsetRect(rcClient.TopLeft());
561 if (m_bHasLines)
562 rcItem.OffsetRect(nIndent, 0);
563 if (SItemPanel::IsItemInClip(mtx, rcClip, rgnClip, rcItem))
564 { // draw the item
565 ii.pItem->Draw(pRT, rcItem);
566 }
567 pt.y += m_tvItemLocator->GetItemHeight(hItem);
568 }
569
570 pRT->PopClip();
571
572 AfterPaint(pRT, painter);
573}
574
575void STreeView::OnSize(UINT nType, CSize size)
576{
577 __baseCls::OnSize(nType, size);
578 if (!m_adapter)
579 return;
582}
583
585{
586 if (m_adapter)
587 {
588 m_adapter->unregisterDataSetObserver(m_observer);
589 }
590
591 // destroy all itempanel
592 SPOSITION pos = m_visible_items.GetHeadPosition();
593 while (pos)
594 {
595 ItemInfo ii = m_visible_items.GetNext(pos);
596 ii.pItem->Release();
597 }
598 m_visible_items.RemoveAll();
599 m_pVisibleMap->RemoveAll();
600
601 for (int i = 0; i < (int)m_itemRecycle.GetCount(); i++)
602 {
603 SList<SItemPanel *> *pLstTypeItems = m_itemRecycle[i];
604 SPOSITION pos = pLstTypeItems->GetHeadPosition();
605 while (pos)
606 {
607 SItemPanel *pItem = pLstTypeItems->GetNext(pos);
608 pItem->Release();
609 }
610 delete pLstTypeItems;
611 }
612 m_itemRecycle.RemoveAll();
613
614 __baseCls::OnDestroy();
615}
616
617void STreeView::EnsureVisible(HSTREEITEM hItem)
618{
619 // 保证hItem被正确展开
620 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
621 while (hParent != ITEM_ROOT)
622 {
623 m_adapter->ExpandItem(hParent, TVC_EXPAND);
624 hParent = m_adapter->GetParentItem(hParent);
625 }
626 // 滚动视图
627 int nPos = m_tvItemLocator->Item2Position(hItem);
628 int nHeight = m_tvItemLocator->GetItemHeight(hItem);
629 if (nPos + nHeight <= m_siVer.nPos)
630 {
631 OnScroll(TRUE, SB_THUMBPOSITION, nPos);
632 }
633 else if (nPos > m_siVer.nPos + (int)m_siVer.nPage)
634 {
635 OnScroll(TRUE, SB_THUMBPOSITION, nPos + nHeight - m_siVer.nPage);
636 }
637 int nIndent = m_tvItemLocator->GetItemIndent(hItem);
638 if (m_bHasLines)
639 nIndent += m_tvItemLocator->GetIndent();
640 int nWidth = m_tvItemLocator->GetItemWidth(hItem);
641
642 if (nIndent + nWidth <= m_siHoz.nPos)
643 {
644 OnScroll(FALSE, SB_THUMBPOSITION, nIndent);
645 }
646 else if (nIndent < m_siHoz.nPos + (int)m_siHoz.nPage)
647 {
648 OnScroll(FALSE, SB_THUMBPOSITION, nIndent + nWidth - m_siHoz.nPage);
649 }
650}
651
652void STreeView::SetSel(HSTREEITEM hItem, BOOL bNotify /*=FALSE*/)
653{
654 if (!m_adapter)
655 return;
656
657 if (bNotify)
658 {
659 EventTVSelChanging evt(this);
660 evt.bCancel = FALSE;
661 evt.hOldSel = m_hSelected;
662 evt.hNewSel = hItem;
663 FireEvent(&evt);
664 if (evt.bCancel)
665 { // Cancel SetSel and restore selection state
666 return;
667 }
668 }
669
670 if (m_hSelected == hItem)
671 return;
672
673 SItemPanel *pItem = GetItemPanel(m_hSelected);
674 if (pItem)
675 {
676 pItem->GetFocusManager()->ClearFocus();
677 pItem->ModifyItemState(0, WndState_Check);
678 RedrawItem(pItem);
679 }
680 m_hSelected = hItem;
681 pItem = GetItemPanel(m_hSelected);
682 if (pItem)
683 {
684 pItem->ModifyItemState(WndState_Check, 0);
685 RedrawItem(pItem);
686 }
687
688 if (bNotify)
689 {
690 EventTVSelChanged evt(this);
691 evt.hOldSel = m_hSelected;
692 evt.hNewSel = hItem;
693 FireEvent(evt);
694 }
695}
696
697void STreeView::OnKeyDown(TCHAR nChar, UINT nRepCnt, UINT nFlags)
698{
699 if (!m_adapter)
700 {
701 SetMsgHandled(FALSE);
702 return;
703 }
704
705 if (m_hSelected != ITEM_NULL && m_bWantTab)
706 {
707 SItemPanel *pItem = GetItemPanel(m_hSelected);
708 if (pItem)
709 {
710 pItem->DoFrameEvent(WM_KEYDOWN, nChar, MAKELONG(nFlags, nRepCnt));
711 if (pItem->IsMsgHandled())
712 return;
713 }
714 }
715
716 SWindow *pOwner = GetOwner();
717 if (pOwner && (nChar == VK_ESCAPE || nChar == VK_RETURN))
718 {
719 pOwner->SSendMessage(WM_KEYDOWN, nChar, MAKELONG(nFlags, nRepCnt));
720 return;
721 }
722
723 HSTREEITEM nNewSelItem = ITEM_NULL;
724 switch (nChar)
725 {
726 case VK_DOWN:
727 nNewSelItem = (m_hSelected == ITEM_NULL) ? m_adapter->GetFirstVisibleItem() : m_adapter->GetNextVisibleItem(m_hSelected);
728 break;
729 case VK_UP:
730 nNewSelItem = (m_hSelected == ITEM_NULL) ? m_adapter->GetFirstVisibleItem() : m_adapter->GetPrevVisibleItem(m_hSelected);
731 break;
732 case VK_PRIOR:
733 OnScroll(TRUE, SB_PAGEUP, 0);
734 break;
735 case VK_NEXT:
736 OnScroll(TRUE, SB_PAGEDOWN, 0);
737 break;
738 case VK_HOME:
739 OnScroll(TRUE, SB_TOP, 0);
740 break;
741 case VK_END:
742 OnScroll(TRUE, SB_BOTTOM, 0);
743 break;
744 case VK_LEFT:
745 if (m_hSelected != ITEM_NULL)
746 {
747 if (m_adapter->HasChildren(m_hSelected) && m_adapter->IsItemExpanded(m_hSelected))
748 m_adapter->ExpandItem(m_hSelected,
749 TVC_COLLAPSE); // collapse the selected item
750 else
751 nNewSelItem = m_adapter->GetPrevVisibleItem(m_hSelected);
752 }
753 break;
754 case VK_RIGHT:
755 if (m_hSelected != ITEM_NULL)
756 {
757 if (m_adapter->HasChildren(m_hSelected) && !m_adapter->IsItemExpanded(m_hSelected))
758 m_adapter->ExpandItem(m_hSelected,
759 TVC_EXPAND); // collapse the selected item
760 else
761 nNewSelItem = m_adapter->GetNextVisibleItem(m_hSelected);
762 }
763 break;
764 }
765
766 if (nNewSelItem != ITEM_NULL)
767 {
768 EnsureVisible(nNewSelItem);
769 SetSel(nNewSelItem, TRUE);
770 }
771 else
772 {
773 SetMsgHandled(FALSE);
774 }
775}
776
777LRESULT STreeView::OnKeyEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
778{
779 LRESULT lRet = 0;
780 SItemPanel *pItem = GetItemPanel(m_hSelected);
781 if (pItem)
782 {
783 lRet = pItem->DoFrameEvent(uMsg, wParam, lParam);
784 SetMsgHandled(pItem->IsMsgHandled());
785 }
786 else
787 {
788 SetMsgHandled(FALSE);
789 }
790 return lRet;
791}
792
794{
795 CSize szView;
796 szView.cx = m_tvItemLocator->GetTotalWidth();
797 if (m_bHasLines)
798 szView.cx += m_tvItemLocator->GetIndent();
799 szView.cy = m_tvItemLocator->GetTotalHeight();
800
801 CRect rcClient;
802 SWindow::GetClientRect(&rcClient); // 不计算滚动条大小
803 CSize size = rcClient.Size();
804 // 关闭滚动条
805 m_wBarVisible = SSB_NULL;
806
807 if (size.cy < szView.cy || (size.cy < szView.cy + GetSbWidth() && size.cx < szView.cx))
808 {
809 // 需要纵向滚动条
810 m_wBarVisible |= SSB_VERT;
811 m_siVer.nMin = 0;
812 m_siVer.nMax = szView.cy - 1;
813 m_siVer.nPage = rcClient.Height();
814
815 if (size.cx - GetSbWidth() < szView.cx && !m_adapter->isViewWidthMatchParent())
816 {
817 // 需要横向滚动条
818 m_wBarVisible |= SSB_HORZ;
819 m_siVer.nPage = size.cy - GetSbWidth() > 0 ? size.cy - GetSbWidth() : 0; // 注意同时调整纵向滚动条page信息
820
821 m_siHoz.nMin = 0;
822 m_siHoz.nMax = szView.cx - 1;
823 m_siHoz.nPage = (size.cx - GetSbWidth()) > 0 ? (size.cx - GetSbWidth()) : 0;
824 }
825 else
826 {
827 // 不需要横向滚动条
828 m_siHoz.nPage = size.cx;
829 m_siHoz.nMin = 0;
830 m_siHoz.nMax = m_siHoz.nPage - 1;
831 m_siHoz.nPos = 0;
832 }
833 }
834 else
835 {
836 // 不需要纵向滚动条
837 m_siVer.nPage = size.cy;
838 m_siVer.nMin = 0;
839 m_siVer.nMax = size.cy - 1;
840 m_siVer.nPos = 0;
841
842 if (size.cx < szView.cx && !m_adapter->isViewWidthMatchParent())
843 {
844 // 需要横向滚动条
845 m_wBarVisible |= SSB_HORZ;
846 m_siHoz.nMin = 0;
847 m_siHoz.nMax = szView.cx - 1;
848 m_siHoz.nPage = size.cx;
849 }
850 else
851 {
852 // 不需要横向滚动条
853 m_siHoz.nPage = size.cx;
854 m_siHoz.nMin = 0;
855 m_siHoz.nMax = m_siHoz.nPage - 1;
856 m_siHoz.nPos = 0;
857 }
858 }
859
860 // 根据需要调整原点位置
861 if (HasScrollBar(FALSE) && m_siHoz.nPos + (int)m_siHoz.nPage > szView.cx)
862 {
863 m_siHoz.nPos = szView.cx - m_siHoz.nPage;
864 }
865
866 if (HasScrollBar(TRUE) && m_siVer.nPos + (int)m_siVer.nPage > szView.cy)
867 {
868 m_siVer.nPos = szView.cy - m_siVer.nPage;
869 }
870
871 SetScrollPos(TRUE, m_siVer.nPos, TRUE);
872 SetScrollPos(FALSE, m_siHoz.nPos, TRUE);
873
874 // 重新计算客户区及非客户区
875 SSendMessage(WM_NCCALCSIZE);
876
877 InvalidateRect(NULL);
878}
879
881{
882 if (!m_adapter)
883 return;
884 SAutoEnableHostPrivUiDef enableUiDef(this);
885 HSTREEITEM hItem = m_tvItemLocator->Position2Item(m_siVer.nPos);
886 if (hItem == ITEM_NULL)
887 {
888 // 如果没有可显示的,则移除所有item
889 SPOSITION pos = m_visible_items.GetHeadPosition();
890 while (pos)
891 {
892 ItemInfo ii = m_visible_items.GetNext(pos);
893
894 if (ii.pItem == m_pHoverItem)
895 {
896 m_pHoverItem->DoFrameEvent(WM_MOUSELEAVE, 0, 0);
897 m_pHoverItem = NULL;
898 }
899
900 ii.pItem->GetEventSet()->setMutedState(true);
901 if ((HSTREEITEM)ii.pItem->GetItemIndex() == m_hSelected)
902 {
903 ii.pItem->ModifyItemState(0, WndState_Check);
904 ii.pItem->GetFocusManager()->ClearFocus();
905 }
906 ii.pItem->SetVisible(FALSE); // 防止执行SItemPanel::OnTimeFrame()
907 ii.pItem->GetEventSet()->setMutedState(false);
908
909 m_itemRecycle[ii.nType]->AddTail(ii.pItem);
910 }
911 m_visible_items.RemoveAll();
912 m_pVisibleMap->RemoveAll();
913 return;
914 }
915
916 CSize szOldView;
917 szOldView.cx = m_tvItemLocator->GetTotalWidth();
918 if (m_bHasLines)
919 szOldView.cx += m_tvItemLocator->GetIndent();
920 szOldView.cy = m_tvItemLocator->GetTotalHeight();
921
922 VISIBLEITEMSMAP *pMapOld = m_pVisibleMap;
923 m_pVisibleMap = new VISIBLEITEMSMAP;
924
925 CRect rcClient = GetClientRect();
926 int nOffset = m_tvItemLocator->Item2Position(hItem) - m_siVer.nPos;
927
928 m_visible_items.RemoveAll();
929 while (hItem != ITEM_NULL)
930 {
931 VISIBLEITEMSMAP::CPair *pFind = pMapOld->Lookup(hItem);
932 ItemInfo ii;
933 ii.nType = m_adapter->getViewType(hItem);
934 BOOL bNewItem = FALSE;
935 if (pFind && pFind->m_value.nType == ii.nType)
936 { // re use the previous item;
937 ii = pFind->m_value;
938 pMapOld->RemoveKey(hItem);
939 }
940 else
941 {
942 SList<SItemPanel *> *lstRecycle = m_itemRecycle.GetAt(ii.nType);
943 if (lstRecycle->IsEmpty())
944 { // 创建一个新的列表项
945 bNewItem = TRUE;
946 ii.pItem = SItemPanel::Create(this, SXmlNode(), this);
947 ii.pItem->GetEventSet()->subscribeEvent(EventItemPanelClick::EventID, Subscriber(&STreeView::OnItemClick, this));
948 }
949 else
950 {
951 ii.pItem = lstRecycle->RemoveHead();
952 }
953 ii.pItem->SetItemIndex(hItem);
954 }
955 m_pVisibleMap->SetAt(hItem, ii);
956 ii.pItem->SetVisible(TRUE);
957
958 if (hItem == m_hSelected)
959 ii.pItem->ModifyItemState(WndState_Check, 0);
960 else
961 ii.pItem->ModifyItemState(0, WndState_Check);
962
963 if (m_pHoverItem && hItem == (HSTREEITEM)m_pHoverItem->GetItemIndex())
964 ii.pItem->ModifyItemState(WndState_Hover, 0);
965 else
966 ii.pItem->ModifyItemState(0, WndState_Hover);
967
968 SXmlNode xmlNode = m_xmlTemplate.root().first_child();
969 ii.pItem->LockUpdate();
970 m_adapter->getView(hItem, ii.pItem, &xmlNode);
971 ii.pItem->UnlockUpdate();
972 if (bNewItem)
973 {
974 ii.pItem->SDispatchMessage(UM_SETSCALE, GetScale(), 0);
975 ii.pItem->SDispatchMessage(UM_SETLANGUAGE, 0, 0);
976 ii.pItem->DoColorize(GetColorizeColor());
977 }
978
979 CSize szItem;
980 CRect rcItem = GetClientRect();
981 m_adapter->getViewDesiredSize(&szItem, hItem, ii.pItem, -1, -1);
982 // 不使宽度
983 if (m_adapter->isViewWidthMatchParent())
984 szItem.cx = rcItem.Width();
985 ii.pItem->Move(CRect(0, 0, szItem.cx, szItem.cy));
986 m_tvItemLocator->SetItemWidth(hItem, szItem.cx);
987 m_tvItemLocator->SetItemHeight(hItem, szItem.cy);
988
989 m_visible_items.AddTail(ii);
990 nOffset += szItem.cy;
991 if (nOffset >= rcClient.Height())
992 break;
993 hItem = m_adapter->GetNextVisibleItem(hItem);
994 }
995
996 SPOSITION pos = pMapOld->GetStartPosition();
997 while (pos)
998 {
999 ItemInfo ii = pMapOld->GetNextValue(pos);
1000
1001 if (ii.pItem == m_pHoverItem)
1002 {
1003 m_pHoverItem->DoFrameEvent(WM_MOUSELEAVE, 0, 0);
1004 m_pHoverItem = NULL;
1005 }
1006
1007 ii.pItem->GetEventSet()->setMutedState(true);
1008 if ((HSTREEITEM)ii.pItem->GetItemIndex() == m_hSelected)
1009 {
1010 ii.pItem->ModifyItemState(0, WndState_Check);
1011 ii.pItem->GetFocusManager()->ClearFocus();
1012 m_hSelected = 0;
1013 }
1014 ii.pItem->SetVisible(FALSE); // 防止执行SItemPanel::OnTimeFrame()
1015 ii.pItem->GetEventSet()->setMutedState(false);
1016
1017 m_itemRecycle[ii.nType]->AddTail(ii.pItem);
1018 }
1019 delete pMapOld;
1020
1021 CSize szNewView;
1022 szNewView.cx = m_tvItemLocator->GetTotalWidth();
1023 if (m_bHasLines)
1024 szNewView.cx += m_tvItemLocator->GetIndent();
1025 szNewView.cy = m_tvItemLocator->GetTotalHeight();
1026 if (szOldView != szNewView)
1027 { // update scroll range
1029 UpdateVisibleItems(); // 根据新的滚动条状态重新记算显示列表项
1030 }
1031 else
1032 {
1033 InvalidateRect(NULL);
1034 }
1035}
1036
1037void STreeView::OnItemSetCapture(SOsrPanel *pItem, BOOL bCapture)
1038{
1039 if (bCapture)
1040 {
1042 m_itemCapture = pItem;
1043 }
1044 else
1045 {
1047 m_itemCapture = NULL;
1048 }
1049}
1050
1051BOOL STreeView::OnItemGetRect(const SOsrPanel *pItem, CRect &rcItem) const
1052{
1053 HSTREEITEM hItem = (HSTREEITEM)pItem->GetItemIndex();
1054 if (m_pVisibleMap->Lookup(hItem) == NULL)
1055 return FALSE;
1056
1057 int nOffset = m_tvItemLocator->Item2Position(hItem) - m_siVer.nPos;
1058 rcItem = GetClientRect();
1059 rcItem.top += nOffset;
1060 rcItem.bottom = rcItem.top + m_tvItemLocator->GetItemHeight(hItem);
1061 rcItem.left += m_tvItemLocator->GetItemIndent(hItem) - m_siHoz.nPos;
1062 rcItem.right = rcItem.left + m_tvItemLocator->GetItemWidth(hItem);
1063 if (m_bHasLines)
1064 {
1065 rcItem.OffsetRect(m_tvItemLocator->GetIndent(), 0);
1066 }
1067 return TRUE;
1068}
1069
1071{
1072 return TRUE;
1073}
1074
1075void STreeView::onBranchChanged(HSTREEITEM hBranch)
1076{
1077 if (m_adapter == NULL)
1078 {
1079 return;
1080 }
1081 if (m_tvItemLocator)
1082 m_tvItemLocator->OnBranchChanged(hBranch);
1085}
1086
1087void STreeView::onBranchInvalidated(HSTREEITEM hBranch, BOOL bInvalidParents, BOOL bInvalidChildren)
1088{
1089 if (m_adapter == NULL)
1090 {
1091 return;
1092 }
1093 SAutoEnableHostPrivUiDef enableUiDef(this);
1094 if (bInvalidParents)
1095 {
1096 HSTREEITEM hParent = m_adapter->GetParentItem(hBranch);
1097 while (hParent)
1098 {
1099 SItemPanel *pItem = GetItemPanel(hParent);
1100 if (pItem)
1101 {
1102 SXmlNode xmlNode = m_xmlTemplate.root().first_child();
1103 m_adapter->getView(hParent, pItem, &xmlNode);
1104 pItem->InvalidateRect(NULL);
1105 }
1106 hParent = m_adapter->GetParentItem(hParent);
1107 }
1108 }
1109 if (!bInvalidChildren)
1110 {
1111 SItemPanel *pItem = GetItemPanel(hBranch);
1112 if (pItem)
1113 {
1114 SXmlNode xmlNode = m_xmlTemplate.root().first_child();
1115 m_adapter->getView(hBranch, pItem, &xmlNode);
1116 pItem->InvalidateRect(NULL);
1117 }
1118 }
1119 else
1120 {
1121 SPOSITION pos = m_visible_items.GetHeadPosition();
1122 while (pos)
1123 {
1124 const ItemInfo &ii = m_visible_items.GetNext(pos);
1125 bool bInvalid = false;
1126 HSTREEITEM hItem = (HSTREEITEM)ii.pItem->GetItemIndex();
1127 while (hItem)
1128 {
1129 if (hItem == hBranch)
1130 {
1131 bInvalid = true;
1132 break;
1133 }
1134 hItem = m_adapter->GetParentItem(hItem);
1135 }
1136 if (bInvalid)
1137 {
1138 SXmlNode xmlNode = m_xmlTemplate.root().first_child();
1139 m_adapter->getView(hBranch, ii.pItem, &xmlNode);
1140 ii.pItem->InvalidateRect(NULL);
1141 }
1142 }
1143 }
1144}
1145
1146void STreeView::onBranchExpandedChanged(HSTREEITEM hBranch, BOOL bExpandedOld, BOOL bExpandedNew)
1147{
1148 if (m_adapter == NULL)
1149 {
1150 return;
1151 }
1152 if (m_tvItemLocator)
1153 m_tvItemLocator->OnBranchExpandedChanged(hBranch, bExpandedOld, bExpandedNew);
1156}
1157
1158void STreeView::onItemBeforeRemove(HSTREEITEM hItem)
1159{
1160 if (m_adapter == NULL)
1161 {
1162 return;
1163 }
1164 if (m_hSelected && (m_hSelected == hItem || m_adapter->IsDecendentItem(hItem, m_hSelected)))
1165 {
1166 m_hSelected = 0;
1167 }
1168
1169 if (m_pHoverItem)
1170 {
1171 HSTREEITEM hHover = m_pHoverItem->GetItemIndex();
1172 if (hHover == hItem || m_adapter->IsDecendentItem(hItem, hHover))
1173 {
1174 m_pHoverItem->DoFrameEvent(WM_MOUSELEAVE, 0, 0);
1175 m_pHoverItem = NULL;
1176 }
1177 }
1178 if (m_itemCapture)
1179 {
1180 HSTREEITEM hCapture = m_itemCapture->GetItemIndex();
1181 if (hCapture == hItem || m_adapter->IsDecendentItem(hItem, hCapture))
1182 {
1183 m_itemCapture = NULL;
1184 }
1185 }
1186}
1187
1188LRESULT STreeView::OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
1189{
1190 SetMsgHandled(FALSE);
1191 if (m_adapter == NULL)
1192 {
1193 return 0;
1194 }
1195
1196 LRESULT lRet = 0;
1197 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1198
1199 if (m_itemCapture)
1200 {
1201 CRect rcItem = m_itemCapture->GetItemRect();
1202 pt.Offset(-rcItem.TopLeft());
1203 lRet = m_itemCapture->DoFrameEvent(uMsg, wParam, MAKELPARAM(pt.x, pt.y));
1204 }
1205 else
1206 {
1207 if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN)
1208 { // 交给panel处理
1209 CPoint pt2(pt);
1210 SItemPanel *pPanel = HitTest(pt2);
1211 if (!pPanel && m_hSelected) // hit in none-item area,so make item to killfocus
1212 {
1213 SItemPanel *pSelItem = GetItemPanel(m_hSelected);
1214 if (pSelItem)
1215 pSelItem->DoFrameEvent(WM_KILLFOCUS, 0, 0);
1216 // m_hSelected = NULL;
1217 }
1218
1219 __baseCls::ProcessSwndMessage(uMsg, wParam, lParam, lRet);
1220 }
1221
1222 SOsrPanel *pHover = HitTest(pt);
1223 if (pHover != m_pHoverItem)
1224 {
1225 SOsrPanel *oldHover = m_pHoverItem;
1226 m_pHoverItem = pHover;
1227 if (oldHover)
1228 {
1229 oldHover->DoFrameEvent(WM_MOUSELEAVE, 0, 0);
1230 oldHover->InvalidateRect(NULL);
1231 }
1232 if (m_pHoverItem)
1233 {
1234 m_pHoverItem->DoFrameEvent(WM_MOUSEHOVER, 0, 0);
1235 m_pHoverItem->InvalidateRect(NULL);
1236 }
1237 }
1238
1239 if (m_pHoverItem)
1240 {
1241 m_pHoverItem->DoFrameEvent(uMsg, wParam, MAKELPARAM(pt.x, pt.y));
1242 }
1243 }
1244
1245 if (uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP)
1246 { // 交给panel处理
1247 __baseCls::ProcessSwndMessage(uMsg, wParam, lParam, lRet);
1248 }
1249 SetMsgHandled(TRUE);
1250 return 0;
1251}
1252
1253void STreeView::RedrawItem(SItemPanel *pItem)
1254{
1255 pItem->InvalidateRect(NULL);
1256}
1257
1259{
1260 __baseCls::OnMouseLeave();
1261
1262 if (m_pHoverItem)
1263 {
1264 m_pHoverItem->DoFrameEvent(WM_MOUSELEAVE, 0, 0);
1265 m_pHoverItem = NULL;
1266 }
1267}
1268
1269BOOL STreeView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
1270{
1271 SItemPanel *pSelItem = GetItemPanel(m_hSelected);
1272 if (pSelItem)
1273 {
1274 CRect rcItem = pSelItem->GetItemRect();
1275 CPoint pt2 = pt - rcItem.TopLeft();
1276 if (pSelItem->DoFrameEvent(WM_MOUSEWHEEL, MAKEWPARAM(nFlags, zDelta), MAKELPARAM(pt2.x, pt2.y)))
1277 return TRUE;
1278 }
1279 return __baseCls::OnMouseWheel(nFlags, zDelta, pt);
1280}
1281
1282void STreeView::OnKillFocus(SWND wndFocus)
1283{
1284 __baseCls::OnKillFocus(wndFocus);
1285 SItemPanel *itemPanel = GetItemPanel(m_hSelected);
1286 if (itemPanel)
1287 itemPanel->GetFocusManager()->StoreFocusedView();
1288}
1289
1290void STreeView::OnSetFocus(SWND wndOld)
1291{
1292 __baseCls::OnSetFocus(wndOld);
1293 SItemPanel *itemPanel = GetItemPanel(m_hSelected);
1294 if (itemPanel)
1295 {
1296 itemPanel->GetFocusManager()->RestoreFocusedView();
1297 }
1298}
1299BOOL STreeView::OnScroll(BOOL bVertical, UINT uCode, int nPos)
1300{
1301 int nOldPos = m_siVer.nPos;
1302 __baseCls::OnScroll(bVertical, uCode, nPos);
1303 int nNewPos = m_siVer.nPos;
1304 if (nOldPos != nNewPos)
1305 {
1307
1308 // 加速滚动时UI的刷新
1309 if (uCode == SB_THUMBTRACK)
1310 ScrollUpdate();
1311
1312 return TRUE;
1313 }
1314 return FALSE;
1315}
1316
1318{
1319 return m_tvItemLocator->GetScrollLineSize();
1320}
1321
1322SItemPanel *STreeView::GetItemPanel(HSTREEITEM hItem)
1323{
1324 VISIBLEITEMSMAP::CPair *pNode = m_pVisibleMap->Lookup(hItem);
1325 if (!pNode)
1326 return NULL;
1327 return pNode->m_value.pItem;
1328}
1329
1330IItemPanel *STreeView::HitTest(const POINT *pt) const
1331{
1332 SASSERT(pt);
1333 if (!pt)
1334 return NULL;
1335 CPoint pt2(*pt);
1336 return HitTest(pt2);
1337}
1338
1339SItemPanel *STreeView::HitTest(CPoint &pt) const
1340{
1341 SPOSITION pos = m_visible_items.GetHeadPosition();
1342 while (pos)
1343 {
1344 ItemInfo ii = m_visible_items.GetNext(pos);
1345 CRect rcItem = ii.pItem->GetItemRect();
1346 if (rcItem.PtInRect(pt))
1347 {
1348 pt -= rcItem.TopLeft();
1349 return ii.pItem;
1350 }
1351 }
1352 return NULL;
1353}
1354
1355BOOL STreeView::OnItemClick(IEvtArgs *pEvt)
1356{
1357 SItemPanel *pItemPanel = sobj_cast<SItemPanel>(pEvt->Sender());
1358 HSTREEITEM hItem = (HSTREEITEM)pItemPanel->GetItemIndex();
1359 if (hItem != m_hSelected)
1360 {
1361 SetSel(hItem, TRUE);
1362 }
1363 return TRUE;
1364}
1365
1366BOOL STreeView::OnItemDblClick(IEvtArgs *pEvt)
1367{
1368 SItemPanel *pItemPanel = sobj_cast<SItemPanel>(pEvt->Sender());
1369 HSTREEITEM hItem = (HSTREEITEM)pItemPanel->GetItemIndex();
1370 if (m_adapter->HasChildren(hItem))
1371 {
1372 m_adapter->ExpandItem(hItem, TVC_TOGGLE);
1373 }
1374 return true;
1375}
1376
1378{
1379 if (m_bWantTab)
1380 return SC_WANTALLKEYS;
1381 else
1382 return SC_WANTARROWS | SC_WANTSYSKEY;
1383}
1384
1385BOOL STreeView::OnSetCursor(const CPoint &pt)
1386{
1387 BOOL bRet = FALSE;
1388 if (m_itemCapture)
1389 {
1390 CRect rcItem = m_itemCapture->GetItemRect();
1391 bRet = m_itemCapture->DoFrameEvent(WM_SETCURSOR, 0, MAKELPARAM(pt.x - rcItem.left, pt.y - rcItem.top)) != 0;
1392 }
1393 else if (m_pHoverItem)
1394 {
1395 CRect rcItem = m_pHoverItem->GetItemRect();
1396 bRet = m_pHoverItem->DoFrameEvent(WM_SETCURSOR, 0, MAKELPARAM(pt.x - rcItem.left, pt.y - rcItem.top)) != 0;
1397 }
1398 if (!bRet)
1399 {
1400 bRet = __baseCls::OnSetCursor(pt);
1401 }
1402 return bRet;
1403}
1404
1406{
1407 if (!m_pHoverItem)
1408 return __baseCls::UpdateToolTip(pt, tipInfo);
1409 return m_pHoverItem->UpdateToolTip(pt, tipInfo);
1410}
1411
1412HRESULT STreeView::OnAttrIndent(const SStringW &strValue, BOOL bLoading)
1413{
1414 if (!bLoading)
1415 return E_FAIL;
1416 m_indent.parseString(strValue);
1417 m_tvItemLocator->SetIndent(m_indent.toPixelSize(GetScale()));
1418 return S_OK;
1419}
1420
1421void STreeView::OnColorize(COLORREF cr)
1422{
1423 __baseCls::OnColorize(cr);
1424 DispatchMessage2Items(UM_SETCOLORIZE, cr, 0);
1425}
1426
1428{
1429 __baseCls::OnScaleChanged(nScale);
1430 GetScaleSkin(m_pLineSkin, nScale);
1431 m_tvItemLocator->SetIndent(m_indent.toPixelSize(nScale));
1432 DispatchMessage2Items(UM_SETSCALE, nScale, 0);
1434}
1435
1437{
1438 HRESULT hret = __baseCls::OnLanguageChanged();
1439 DispatchMessage2Items(UM_SETLANGUAGE, 0, 0);
1440 return hret;
1441}
1442
1443void STreeView::DispatchMessage2Items(UINT uMsg, WPARAM wParam, LPARAM lParam)
1444{
1445 SPOSITION pos = m_visible_items.GetHeadPosition();
1446 while (pos)
1447 {
1448 ItemInfo ii = m_visible_items.GetNext(pos);
1449 ii.pItem->SDispatchMessage(uMsg, wParam, lParam);
1450 }
1451 for (UINT i = 0; i < m_itemRecycle.GetCount(); i++)
1452 {
1453 SList<SItemPanel *> *pLstTypeItems = m_itemRecycle[i];
1454 SPOSITION pos = pLstTypeItems->GetHeadPosition();
1455 while (pos)
1456 {
1457 SItemPanel *pItem = pLstTypeItems->GetNext(pos);
1458 pItem->SDispatchMessage(uMsg, wParam, lParam);
1459 }
1460 }
1461}
1462
1464{
1465 __baseCls::OnRebuildFont();
1466 DispatchMessage2Items(UM_UPDATEFONT, 0, 0);
1467 UpdateVisibleItems(); // 防止因为字体大小变化后,列表项大小发生变化没有更新。其它view不需要这个过程。
1468}
1469
1470ITvAdapter *STreeView::GetAdapter() const
1471{
1472 return m_adapter;
1473}
1474
1475void STreeView::SetItemLocator(ITreeViewItemLocator *pItemLocator)
1476{
1477 m_tvItemLocator = pItemLocator;
1478}
1479
1480ITreeViewItemLocator *STreeView::GetItemLocator() const
1481{
1482 return m_tvItemLocator;
1483}
1484
1485HSTREEITEM STreeView::GetSel() const
1486{
1487 return m_hSelected;
1488}
1489
1490void STreeView::DrawLines(IRenderTarget *pRT, const CRect &rc, HSTREEITEM hItem)
1491{
1492 int nIndent = m_tvItemLocator->GetIndent();
1493 if (nIndent == 0 || !m_pLineSkin || !m_bHasLines)
1494 return;
1495 SList<HSTREEITEM> lstParent;
1496 HSTREEITEM hParent = m_adapter->GetParentItem(hItem);
1497 while (hParent && hParent != STVI_ROOT)
1498 {
1499 lstParent.AddHead(hParent);
1500 hParent = m_adapter->GetParentItem(hParent);
1501 }
1502 // draw parent flags.
1503 enum
1504 {
1505 plus,
1506 plus_join,
1507 plus_bottom,
1508 minus,
1509 minus_join,
1510 minus_bottom,
1511 line,
1512 line_join,
1513 line_bottom,
1514 line_root,
1515 }; // 10 line states
1516 CRect rcLine = rc;
1517 rcLine.right = rcLine.left + nIndent;
1518 SPOSITION pos = lstParent.GetHeadPosition();
1519 while (pos)
1520 {
1521 HSTREEITEM hParent = lstParent.GetNext(pos);
1522 HSTREEITEM hNextSibling = m_adapter->GetNextSiblingItem(hParent);
1523 if (hNextSibling)
1524 {
1525 m_pLineSkin->DrawByIndex(pRT, rcLine, line);
1526 }
1527 rcLine.OffsetRect(nIndent, 0);
1528 }
1529 BOOL hasNextSibling = m_adapter->GetNextSiblingItem(hItem) != 0;
1530 BOOL hasPervSibling = m_adapter->GetPrevSiblingItem(hItem) != 0;
1531 BOOL hasChild = m_adapter->HasChildren(hItem);
1532 bool hasParent = m_adapter->GetParentItem(hItem) != STVI_ROOT;
1533 int iLine = -1;
1534 if (hasChild)
1535 { // test if is collapsed
1536 if (!m_adapter->IsItemExpanded(hItem))
1537 {
1538 if (!hasParent && !hasPervSibling) // no parent
1539 iLine = plus;
1540 else if (hasNextSibling)
1541 iLine = plus_join;
1542 else
1543 iLine = plus_bottom;
1544 }
1545 else
1546 {
1547 if (!hasParent && !hasPervSibling) // no parent
1548 iLine = minus;
1549 else if (hasNextSibling)
1550 iLine = minus_join;
1551 else
1552 iLine = minus_bottom;
1553 }
1554 }
1555 else
1556 {
1557 if (hasNextSibling)
1558 {
1559 if (!hasParent && !hasPervSibling)
1560 iLine = line_root;
1561 else
1562 iLine = line_join;
1563 }
1564 else
1565 iLine = line_bottom;
1566 }
1567 m_pLineSkin->DrawByIndex(pRT, rcLine, iLine);
1568}
1569
1570void STreeView::OnLButtonDown(UINT nFlags, CPoint pt)
1571{
1572 if (m_bHasLines)
1573 {
1574 CPoint pt2 = pt;
1575 int nIndent = m_tvItemLocator->GetIndent();
1576 pt.x += nIndent;
1577 SItemPanel *pHoverItem = HitTest(pt);
1578 if (pHoverItem)
1579 {
1580 CRect rcItem = pHoverItem->GetItemRect();
1581 CRect rcLine(CPoint(rcItem.left - nIndent, rcItem.top + (rcItem.Height() - nIndent) / 2), CSize(nIndent, nIndent));
1582 if (rcLine.PtInRect(pt2))
1583 { // switch toggle state
1584 HSTREEITEM hItem = (HSTREEITEM)pHoverItem->GetItemIndex();
1585 if (m_adapter->HasChildren(hItem))
1586 m_adapter->ExpandItem(hItem, TVC_TOGGLE);
1587 return;
1588 }
1589 }
1590 }
1591 SetMsgHandled(FALSE);
1592}
1593
1594SNSEND
#define STVI_ROOT
Definition STree.h:43
@ WndState_Hover
Definition SWnd.h:76
@ WndState_Check
Definition SWnd.h:78
A helper class to enable or disable private UI definitions for the host container.
Definition SWnd.h:2663
Smart pointer class for managing COM-style reference-counted objects.
BOOL subscribeEvent(DWORD dwEventID, const IEvtSlot &subscriber)
订阅事件
Definition SEventSet.h:151
void setMutedState(BOOL setting)
设置事件集的静音状态
void RestoreFocusedView()
Restores the focused view.
void ClearFocus()
Clears the focused window.
void StoreFocusedView()
Stores the focused view.
The SMatrix class holds a 3x3 matrix for transforming coordinates. SMatrix does not have a constructo...
Definition SMatrix.h:22
Helper class for painting.
Definition SWnd.h:178
virtual CRect GetClientRect() const
Gets the client rectangle.
Definition SPanel.cpp:368
int GetSbWidth() const
Gets the width of the scrollbar.
Definition SPanel.cpp:650
void ScrollUpdate()
Updates the scrollbar.
Definition SPanel.cpp:579
A class representing an ASCII string.
Definition sstringw.h:96
BOOL m_bHasLines
Definition STreeView.h:648
virtual BOOL OnItemGetRect(const SOsrPanel *pItem, CRect &rcItem) const
Gets the rectangle of an item.
virtual void OnItemSetCapture(SOsrPanel *pItem, BOOL bCapture)
Sets or releases mouse capture for an item.
SItemPanel * GetItemPanel(HSTREEITEM hItem)
Gets the item panel for a given item handle.
void OnDestroy()
Handles the destruction event.
void SetSel(HSTREEITEM hItem, BOOL bNotify=FALSE) OVERRIDE
Sets the selected item.
virtual void OnColorize(COLORREF cr)
Applies colorization to the tree view.
ITreeViewItemLocator * GetItemLocator() SCONST OVERRIDE
Gets the item locator for the tree view.
void onBranchChanged(HSTREEITEM hBranch)
Notifies the tree view that a branch has changed.
VISIBLEITEMSMAP * m_pVisibleMap
Definition STreeView.h:638
void onBranchExpandedChanged(HSTREEITEM hBranch, BOOL bExpandedOld, BOOL bExpandedNew)
Notifies the tree view that the expanded state of a branch has changed.
virtual BOOL UpdateToolTip(CPoint pt, SwndToolTipInfo &tipInfo)
Updates the tooltip information.
BOOL SetAdapter(ITvAdapter *adapter) OVERRIDE
Sets the adapter for the tree view.
BOOL OnItemClick(IEvtArgs *pEvt)
Handles the item click event.
SAutoRefPtr< ITvDataSetObserver > m_observer
Definition STreeView.h:626
void OnSetFocus(SWND wndOld)
Handles the set focus event.
void OnKeyDown(TCHAR nChar, UINT nRepCnt, UINT nFlags)
Handles the key down event.
SAutoRefPtr< ISkinObj > m_pLineSkin
Definition STreeView.h:649
SLayoutSize m_indent
Definition STreeView.h:650
void UpdateScrollBar()
Updates the scroll bar.
virtual BOOL IsItemRedrawDelay() const
Indicates if item redraw is delayed.
HSTREEITEM m_hSelected
Definition STreeView.h:645
HSTREEITEM GetSel() SCONST OVERRIDE
Gets the selected item.
LRESULT OnKeyEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
Handles key events.
SArray< SList< SItemPanel * > * > m_itemRecycle
Definition STreeView.h:634
virtual void OnScaleChanged(int nScale)
Handles scale changes.
SAutoRefPtr< ITreeViewItemLocator > m_tvItemLocator
Definition STreeView.h:627
virtual HRESULT OnLanguageChanged()
Handles language change events.
virtual BOOL OnSetCursor(const CPoint &pt)
Sets the cursor for the tree view.
virtual int GetScrollLineSize(BOOL bVertical)
Gets the scroll line size.
void OnKillFocus(SWND wndFocus)
Handles the kill focus event.
BOOL m_bWantTab
Definition STreeView.h:647
virtual BOOL OnScroll(BOOL bVertical, UINT uCode, int nPos)
Handles scroll events.
SOsrPanel * m_pHoverItem
Definition STreeView.h:643
BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
Handles the mouse wheel event.
void EnsureVisible(HSTREEITEM hItem) OVERRIDE
Ensures an item is visible.
SXmlDoc m_xmlTemplate
Definition STreeView.h:640
void RedrawItem(SItemPanel *pItem)
Redraws an item.
SAutoRefPtr< ITvAdapter > m_adapter
Definition STreeView.h:625
void SetItemLocator(ITreeViewItemLocator *pItemLocator) OVERRIDE
Sets the item locator for the tree view.
void UpdateVisibleItems()
Updates the visible items.
ITvAdapter * GetAdapter() SCONST OVERRIDE
Gets the adapter for the tree view.
void OnMouseLeave()
Handles the mouse leave event.
STreeView()
Constructor for STreeView.
virtual void OnRebuildFont()
Rebuilds the font settings.
HRESULT OnAttrIndent(const SStringW &strValue, BOOL bLoading)
Handles the indentation attribute.
IItemPanel * HitTest(const POINT *pt) SCONST OVERRIDE
Performs a hit test on the tree view.
void OnLButtonDown(UINT nFlags, CPoint pt)
Handles the left mouse button down event.
virtual BOOL CreateChildren(SXmlNode xmlNode)
Creates child elements from XML node.
SOsrPanel * m_itemCapture
Definition STreeView.h:642
void onBranchInvalidated(HSTREEITEM hBranch, BOOL bInvalidParents, BOOL bInvalidChildren)
Notifies the tree view that a branch has been invalidated.
void OnSize(UINT nType, CSize size)
Handles the size event.
void onItemBeforeRemove(HSTREEITEM hItem)
Notifies the tree view that an item is about to be removed.
virtual UINT WINAPI OnGetDlgCode() const
Gets the dialog code for the tree view.
void OnPaint(IRenderTarget *pRT)
Handles the paint event.
~STreeView()
Destructor for STreeView.
BOOL OnItemDblClick(IEvtArgs *pEvt)
Handles the item double-click event.
SList< ItemInfo > m_visible_items
Definition STreeView.h:635
void DispatchMessage2Items(UINT uMsg, WPARAM wParam, LPARAM lParam)
Dispatches a message to items.
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
Handles mouse events.
virtual void DrawLines(IRenderTarget *pRT, const CRect &rc, HSTREEITEM hItem)
Draws lines for an item.
Class responsible for locating and managing tree view items.
Definition STreeView.h:17
int _GetItemOffset(HSTREEITEM hItem) const
Gets the offset of an item.
int GetItemIndent(HSTREEITEM hItem) SCONST OVERRIDE
Gets the indentation of an item.
void _SetItemOffset(HSTREEITEM hItem, int nOffset)
Sets the offset of an item.
~STreeViewItemLocator()
Destructor for STreeViewItemLocator.
Definition STreeView.cpp:46
void SetIndent(int nIndent) OVERRIDE
Sets the indentation between levels.
int GetScrollLineSize() SCONST OVERRIDE
Gets the scroll line size.
BOOL IsItemExpanded(HSTREEITEM hItem) const
Checks if an item is expanded.
HSTREEITEM _Position2Item(int position, HSTREEITEM hParent, int nParentPosition) const
Converts a position to an item handle.
Definition STreeView.cpp:95
int GetItemWidth(HSTREEITEM hItem) SCONST OVERRIDE
Gets the width of an item.
int _GetBranchWidth(HSTREEITEM hBranch) const
Gets the width of a branch.
void _UpdateSiblingsOffset(HSTREEITEM hItem)
Updates the offset of sibling items.
void OnBranchExpandedChanged(HSTREEITEM hItem, BOOL bExpandedOld, BOOL bExpandedNew) OVERRIDE
Notifies the locator that the expanded state of a branch has changed.
BOOL _IsItemVisible(HSTREEITEM hItem) const
Checks if an item is visible.
Definition STreeView.cpp:90
void _UpdateBranchHeight(HSTREEITEM hItem, int nDiff)
Updates the height of a branch.
int _GetItemVisibleWidth(HSTREEITEM hItem) const
Gets the visible width of an item.
void _SetBranchWidth(HSTREEITEM hBranch, int nWidth)
Sets the width of a branch.
int GetTotalWidth() SCONST OVERRIDE
Gets the total width of the tree view.
SAutoRefPtr< ITvAdapter > m_adapter
Definition STreeView.h:252
void SetAdapter(ITvAdapter *pAdapter) OVERRIDE
Sets the adapter for the tree view items.
Definition STreeView.cpp:50
HSTREEITEM Position2Item(int position) SCONST OVERRIDE
Converts a position to an item handle.
int GetTotalHeight() SCONST OVERRIDE
Gets the total height of the tree view.
void _SetItemHeight(HSTREEITEM hItem, int nHeight)
Sets the height of an item.
void SetItemHeight(HSTREEITEM hItem, int nHeight) OVERRIDE
Sets the height of an item.
void _InitBranch(HSTREEITEM hItem)
Initializes a branch.
Definition STreeView.cpp:55
int _GetBranchHeight(HSTREEITEM hItem) const
Gets the height of a branch.
int _GetItemVisibleHeight(HSTREEITEM hItem) const
Gets the visible height of an item.
void _SetItemWidth(HSTREEITEM hItem, int nWidth)
Sets the width of an item.
int GetIndent() SCONST OVERRIDE
Gets the indentation between levels.
int GetItemHeight(HSTREEITEM hItem) SCONST OVERRIDE
Gets the height of an item.
void SetItemWidth(HSTREEITEM hItem, int nWidth) OVERRIDE
Sets the width of an item.
int Item2Position(HSTREEITEM hItem) SCONST OVERRIDE
Converts an item handle to its position.
STreeViewItemLocator(int nIndent=16)
Constructor for STreeViewItemLocator.
Definition STreeView.cpp:39
void _SetBranchHeight(HSTREEITEM hItem, int nHeight)
Sets the height of a branch.
void _UpdateBranchWidth(HSTREEITEM hItem, int nOldWidth, int nNewWidth)
Updates the branch width data in the parent window.
void OnBranchChanged(HSTREEITEM hItem) OVERRIDE
Notifies the locator that a branch has changed.
Base class for SOUI DUI windows.
Definition SWnd.h:286
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Fires an event.
Definition Swnd.cpp:1540
void SetVisible(BOOL bVisible, BOOL bUpdate=FALSE) OVERRIDE
Sets the visibility of the window.
Definition Swnd.cpp:655
void UnlockUpdate() OVERRIDE
Unlocks updates to the window.
Definition Swnd.cpp:1497
SWindow * GetOwner() const
Retrieves the current owner of the window.
Definition Swnd.cpp:706
BOOL Destroy() OVERRIDE
Destroys the window.
Definition Swnd.cpp:504
void SDispatchMessage(UINT uMsg, WPARAM wParam=0, LPARAM lParam=0) OVERRIDE
Dispatches a message to the window.
Definition Swnd.cpp:388
int GetScale() SCONST OVERRIDE
Retrieves the scale factor of the window.
Definition Swnd.cpp:3266
BOOL IsMsgHandled() const
Checks if the message is handled.
Definition Swnd.cpp:207
COLORREF GetColorizeColor() SCONST OVERRIDE
Retrieves the colorization color of the window.
Definition Swnd.cpp:3166
ISwndContainer * GetContainer() OVERRIDE
Retrieves the container associated with this window.
Definition Swnd.cpp:679
void DoColorize(COLORREF cr) OVERRIDE
Applies colorization to the window.
Definition Swnd.cpp:3143
virtual CRect GetClientRect() const
Retrieves the client rectangle of the window.
Definition Swnd.cpp:243
LRESULT SSendMessage(UINT uMsg, WPARAM wParam=0, LPARAM lParam=0, BOOL *pbMsgHandled=NULL) OVERRIDE
Sends a message to the window.
Definition Swnd.cpp:364
virtual void BeforePaint(IRenderTarget *pRT, SPainter &painter)
Prepare rendering environment.
Definition Swnd.cpp:1755
void InvalidateRect(LPCRECT lprect) OVERRIDE
Invalidates a specific rectangle area of the window.
Definition Swnd.cpp:1444
BOOL m_bFocusable
Definition SWnd.h:2609
virtual void AfterPaint(IRenderTarget *pRT, SPainter &painter)
Restore rendering environment.
Definition Swnd.cpp:1776
SEventSet * GetEventSet()
Retrieves the event set associated with the window.
Definition SWnd.h:1290
void SetMsgHandled(BOOL bHandled)
Sets the message handled flag.
Definition Swnd.cpp:212
SEventSet m_evtSet
Definition SWnd.h:2581
void GetScaleSkin(SAutoRefPtr< ISkinObj > &pSkin, int nScale)
Retrieves a scaled skin object based on the current scale factor.
Definition Swnd.cpp:3290
void LockUpdate() OVERRIDE
Locks updates to the window.
Definition Swnd.cpp:1492
SWND m_swnd
Member variables representing various properties of the window.
Definition SWnd.h:2577
void Move(LPCRECT prect) OVERRIDE
Moves the window to a new position and size.
Definition Swnd.cpp:399
Class representing an XML node.
Definition SXml.h:352
SXmlNode child(const wchar_t *name, bool bCaseSensitive=false) const
Gets the child node, attribute, or next/previous sibling with the specified name.
Definition SXml.cpp:423
SFocusManager * GetFocusManager()
Retrieves the focus manager.
Template class implementing the IObjRef interface.
Interface for rendering target objects.
Definition SRender-i.h:1440
HRESULT GetTransform(float matrix[9]) SCONST PURE
Retrieves the current coordinate transformation matrix.
HRESULT PushClipRect(LPCRECT pRect, UINT mode=RGN_AND) PURE
Push a rectangular clip region.
HRESULT PopClip() PURE
Pop the last clip region from the stack.
HRESULT GetClipBox(LPRECT prc) PURE
Get the bounding box of the current clip region.
HRESULT GetClipRegion(IRegionS **ppRegion) PURE
Get the current clip region.
BOOL OnReleaseSwndCapture() PURE
Releases the mouse capture from the Swnd object.
SWND OnSetSwndCapture(SWND swnd) PURE
Sets the Swnd object to capture the mouse.
Information for window tooltips.
Definition SWnd.h:208