soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
STabCtrl.cpp
1#include "souistd.h"
2#include "control/STabCtrl.h"
3#include "animation/SInterpolatorImpl.h"
4
5SNSBEGIN
6
7class STabSlider
8 : public SWindow
9 , public ITimelineHandler {
10 DEF_SOBJECT(SWindow, L"tabslider")
11
12 public:
13 STabSlider(STabCtrl *pTabCtrl, int iFrom, int iTo, int nSteps, int nType, IInterpolator *pInterpolator)
14 : m_pTabCtrl(pTabCtrl)
15 , m_aniInterpoloator(pInterpolator)
16 , m_nSteps(nSteps)
17 , m_iStep(0)
18 {
19 SASSERT(pTabCtrl);
20 SASSERT(pInterpolator);
21
22 pTabCtrl->GetRoot()->UpdateLayout();
23
24 CRect rcPage;
25 pTabCtrl->GetChildrenLayoutRect(&rcPage);
26 if (nType == 0)
27 {
28 pTabCtrl->InsertChild(this);
29 Move(rcPage);
30
31 m_bVertical = pTabCtrl->m_nTabAlign == STabCtrl::AlignLeft || pTabCtrl->m_nTabAlign == STabCtrl::AlignRight;
32 if (m_bVertical)
33 {
34 GETRENDERFACTORY->CreateRenderTarget(&m_memRT, rcPage.Width(), rcPage.Height() * 2);
35 }
36 else
37 {
38 GETRENDERFACTORY->CreateRenderTarget(&m_memRT, rcPage.Width() * 2, rcPage.Height());
39 }
40
41 m_memRT->BeginDraw();
42 CPoint pt;
43
44 if (m_bVertical)
45 {
46 if (iFrom < iTo)
47 { // move up
48 pt.x = pt.y = 0;
49 m_nFrom = 0;
50 m_nTo = rcPage.Height();
51 }
52 else
53 { // move down
54 pt.x = 0, pt.y = rcPage.Height();
55 m_ptOffset.y = rcPage.Height();
56 m_nFrom = rcPage.Height();
57 m_nTo = 0;
58 }
59 }
60 else
61 {
62 if (iFrom < iTo)
63 { // move left
64 pt.x = pt.y = 0;
65 m_nFrom = 0;
66 m_nTo = rcPage.Width();
67 }
68 else
69 {
70 pt.x = rcPage.Width(), pt.y = 0;
71 m_ptOffset.x = rcPage.Width();
72 m_nFrom = rcPage.Width();
73 m_nTo = 0;
74 }
75 }
76 pt -= rcPage.TopLeft();
77 m_memRT->SetViewportOrg(pt);
78 PaintBackground(m_memRT, &rcPage);
79
80 pTabCtrl->GetItem(iFrom)->SetVisible(FALSE);
81
82 if (m_bVertical)
83 {
84 if (iFrom < iTo)
85 { // move up
86 pt.x = 0, pt.y = rcPage.Height();
87 }
88 else
89 { // move down
90 pt.x = pt.y = 0;
91 }
92 }
93 else
94 {
95 if (iFrom < iTo)
96 { // move left
97 pt.x = rcPage.Width(), pt.y = 0;
98 }
99 else
100 {
101 pt.x = pt.y = 0;
102 }
103 }
104
105 pt -= rcPage.TopLeft();
106 m_memRT->SetViewportOrg(pt);
107
108 pTabCtrl->GetItem(iTo)->SetVisible(TRUE);
109 PaintBackground(m_memRT, &rcPage);
110
111 m_memRT->SetViewportOrg(CPoint());
112
114 pTabCtrl->GetItem(iTo)->SetVisible(FALSE);
115 SetVisible(TRUE, TRUE);
116 m_memRT->EndDraw();
117 }
118 else
119 {
120 pTabCtrl->InsertChild(this, ICWND_FIRST);
121 Move(rcPage);
122
123 m_bVertical = pTabCtrl->m_nTabAlign == STabCtrl::AlignLeft || pTabCtrl->m_nTabAlign == STabCtrl::AlignRight;
124 if (m_bVertical)
125 {
126 GETRENDERFACTORY->CreateRenderTarget(&m_memRT, rcPage.Width(), rcPage.Height() * 2);
127 }
128 else
129 {
130 GETRENDERFACTORY->CreateRenderTarget(&m_memRT, rcPage.Width() * 2, rcPage.Height());
131 }
132 m_memRT->BeginDraw();
133 CPoint pt;
134
135 if (m_bVertical)
136 {
137 if (iFrom < iTo)
138 { // move up
139 pt.x = pt.y = 0;
140 m_nFrom = 0;
141 m_nTo = rcPage.Height();
142 }
143 else
144 { // move down
145 pt.x = 0, pt.y = rcPage.Height();
146 m_ptOffset.y = rcPage.Height();
147 m_nFrom = rcPage.Height();
148 m_nTo = 0;
149 }
150 }
151 else
152 {
153 if (iFrom < iTo)
154 { // move left
155 pt.x = pt.y = 0;
156 m_nFrom = 0;
157 m_nTo = rcPage.Width();
158 }
159 else
160 {
161 pt.x = rcPage.Width(), pt.y = 0;
162 m_ptOffset.x = rcPage.Width();
163 m_nFrom = rcPage.Width();
164 m_nTo = 0;
165 }
166 }
167 pt -= rcPage.TopLeft();
168 m_memRT->SetViewportOrg(pt);
169 PaintForeground(m_memRT, &rcPage, GetParent());
170
171 pTabCtrl->GetItem(iFrom)->SetVisible(FALSE);
172
173 if (m_bVertical)
174 {
175 if (iFrom < iTo)
176 { // move up
177 pt.x = 0, pt.y = rcPage.Height();
178 }
179 else
180 { // move down
181 pt.x = pt.y = 0;
182 }
183 }
184 else
185 {
186 if (iFrom < iTo)
187 { // move left
188 pt.x = rcPage.Width(), pt.y = 0;
189 }
190 else
191 {
192 pt.x = pt.y = 0;
193 }
194 }
195
196 pt -= rcPage.TopLeft();
197 m_memRT->SetViewportOrg(pt);
198
199 pTabCtrl->GetItem(iTo)->SetVisible(TRUE);
200 PaintForeground(m_memRT, &rcPage, GetParent());
201
202 m_memRT->SetViewportOrg(CPoint());
203 m_memRT->EndDraw();
205 pTabCtrl->GetItem(iTo)->SetVisible(FALSE);
206 SetVisible(TRUE, TRUE);
207 }
208 }
209
210 virtual ~STabSlider()
211 {
212 }
213
214 STDMETHOD_(void, OnNextFrame)(THIS_) OVERRIDE
215 {
216 if (++m_iStep > m_nSteps)
217 {
218 Stop();
219 }
220 else
221 {
222 float fPos = m_aniInterpoloator->getInterpolation(m_iStep * 1.0f / m_nSteps);
223 int nOffset = m_nFrom + (int)(fPos * (m_nTo - m_nFrom));
224 if (m_bVertical)
225 m_ptOffset.y = nOffset;
226 else
227 m_ptOffset.x = nOffset;
228 InvalidateRect(NULL);
229 }
230 }
231
232 void Stop()
233 {
234 m_pTabCtrl->OnSliderFinish();
235 }
236
237 protected:
238 virtual void OnContainerChanged(ISwndContainer *pOldContainer, ISwndContainer *pNewContainer)
239 {
240 if (pOldContainer)
241 pOldContainer->UnregisterTimelineHandler(this);
242 if (pNewContainer)
243 pNewContainer->RegisterTimelineHandler(this);
244 SWindow::OnContainerChanged(pOldContainer, pNewContainer);
245 }
246
247 void OnPaint(IRenderTarget *pRT)
248 {
249 CRect rcWnd = GetWindowRect();
250 CRect rcSrc(m_ptOffset.x, m_ptOffset.y, m_ptOffset.x + rcWnd.Width(), m_ptOffset.y + rcWnd.Height());
251 pRT->AlphaBlend(rcWnd, m_memRT, rcSrc, 255);
252 }
253
254 void OnSize(UINT fType, CSize sz)
255 {
256 SWindow::OnSize(fType, sz);
257 if (!m_memRT)
258 return;
259 Stop();
260 }
261
262 void OnDestroy()
263 {
266 }
267
268 SAutoRefPtr<IRenderTarget> m_memRT;
269 CPoint m_ptOffset;
270 int m_nFrom, m_nTo;
271 int m_nSteps;
272 int m_iStep;
273 bool m_bVertical;
274 SAutoRefPtr<IInterpolator> m_aniInterpoloator;
275 STabCtrl *m_pTabCtrl;
276 SOUI_MSG_MAP_BEGIN()
277 MSG_WM_PAINT_EX(OnPaint)
278 MSG_WM_SIZE(OnSize)
279 MSG_WM_DESTROY(OnDestroy)
280 SOUI_MSG_MAP_END()
281};
282
283//////////////////////////////////////////////////////////////////////////
284// STabCtrl
285
287 : m_nCurrentPage(0)
288 , m_pSkinTab(GETBUILTINSKIN(SKIN_SYS_TAB_PAGE))
289 , m_pSkinIcon(NULL)
290 , m_pSkinTabInter(NULL)
291 , m_pSkinFrame(NULL)
293 , m_nTabPos(0, SLayoutSize::px)
294 , m_nHoverTabItem(-1)
295 , m_nTabAlign(AlignTop)
296 , m_nAnimateSteps(0)
297 , m_tabSlider(NULL)
298 , m_txtDir(Text_Horz)
299 , m_nAniamteType(0)
300{
301 m_ptText[0] = m_ptText[1] = SLayoutSize(-1.f, SLayoutSize::px);
302 m_szTab[0] = m_szTab[1] = SLayoutSize(-1.f, SLayoutSize::px);
303
304 m_bFocusable = TRUE;
305 // create a linear animation interpolator
306 m_aniInterpolator.Attach(SApplication::getSingleton().CreateInterpolatorByName(SLinearInterpolator::GetClassName()));
307
308 m_evtSet.addEvent(EVENTID(EventTabSelChanging));
309 m_evtSet.addEvent(EVENTID(EventTabSelChanged));
310 m_evtSet.addEvent(EVENTID(EventTabItemHover));
311 m_evtSet.addEvent(EVENTID(EventTabItemLeave));
312}
313
315{
316 SPainter painter;
317 BeforePaint(pRT, painter);
318
319 CRect rcTitle = GetTitleRect();
320
321 if (!rcTitle.IsRectEmpty())
322 {
323 CRect rcItem, rcItemPrev;
324 CRect rcSplit;
325 DWORD dwState;
326
327 pRT->PushClipRect(&rcTitle, RGN_AND);
328
329 for (int i = 0; i < (int)GetItemCount(); i++)
330 {
331 dwState = WndState_Normal;
332 if (i == m_nCurrentPage)
333 dwState = WndState_PushDown;
334 else if (i == m_nHoverTabItem)
335 dwState = WndState_Hover;
336
337 GetItemRect(i, rcItem);
338 if (rcItem.IsRectEmpty())
339 continue;
340
341 //画分隔线
342 if (i > 0 && m_pSkinTabInter)
343 {
344 rcSplit = rcItem;
345 if (m_nTabAlign == AlignLeft)
346 {
347 rcSplit.top = rcItemPrev.bottom;
348 rcSplit.bottom = rcSplit.top + m_nTabInterSize.toPixelSize(GetScale());
349 }
350 else
351 {
352 rcSplit.left = rcItemPrev.right;
353 rcSplit.right = rcSplit.left + m_nTabInterSize.toPixelSize(GetScale());
354 }
355 m_pSkinTabInter->DrawByIndex(pRT, rcSplit, 0);
356 }
357
358 DrawItem(pRT, rcItem, i, dwState);
359 rcItemPrev = rcItem;
360 }
361 pRT->PopClip();
362 }
363 if (m_pSkinFrame)
364 {
365 CRect rcPage;
366 GetChildrenLayoutRect(&rcPage);
367 m_pSkinFrame->DrawByState(pRT, rcPage, WndState_Normal);
368 }
369
371 {
372 CRect rc;
374 rc.DeflateRect(2, 2);
375 DrawDefFocusRect(pRT, &rc);
376 }
377 AfterPaint(pRT, painter);
378}
379
381{
382 CRect rcRet;
383 GetClientRect(rcRet);
384 rcRet.DeflateRect(GetStyle().GetPadding());
385 switch (m_nTabAlign)
386 {
387 case AlignLeft:
388 rcRet.left += m_szTab[0].toPixelSize(GetScale());
389 break;
390 case AlignRight:
391 rcRet.right -= m_szTab[0].toPixelSize(GetScale());
392 break;
393 case AlignTop:
394 rcRet.top += m_szTab[1].toPixelSize(GetScale());
395 break;
396 case AlignBottom:
397 rcRet.bottom -= m_szTab[1].toPixelSize(GetScale());
398 break;
399 }
400 *prc = rcRet;
401}
402
403void STabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
404{
405 SWindow::OnLButtonDown(nFlags, point);
406 int iClickItem = HitTest(point);
407 if (iClickItem != m_nCurrentPage)
408 {
409 SetCurSel(iClickItem);
410 }
411}
412
413BOOL STabCtrl::RemoveItem(int nIndex, int nSelPage /*=0*/)
414{
415 STabPage *pTab = GetItem(nIndex);
416 OnItemRemoved(pTab);
417
418 DestroyChild(pTab);
419 m_lstPages.RemoveAt(nIndex);
420
421 if (m_nCurrentPage == nIndex)
422 {
423 if (nSelPage < 0)
424 nSelPage = 0;
425 if (nSelPage >= GetItemCount())
426 nSelPage = GetItemCount() - 1;
427 m_nCurrentPage = -1;
428 SetCurSel(nSelPage);
429 }
430 else
431 {
432 if (m_nCurrentPage > nIndex)
434 }
435 CRect rcTitle = GetTitleRect();
436 InvalidateRect(rcTitle);
437 return TRUE;
438}
439
441{
442 for (int i = GetItemCount() - 1; i >= 0; i--)
443 {
444 STabPage *pTab = GetItem(i);
445 OnItemRemoved(pTab);
446 DestroyChild(pTab);
447 m_lstPages.RemoveAt(i);
448 }
449 m_nCurrentPage = -1;
450 Invalidate();
451}
452
453void STabCtrl::OnMouseMove(UINT nFlags, CPoint point)
454{
455 CRect rcItem;
456 int nOldHover = m_nHoverTabItem;
457 m_nHoverTabItem = -1;
458 int nTabCount = GetItemCount();
459 for (int i = 0; i < nTabCount; i++)
460 {
461 GetItemRect(i, rcItem);
462
463 if (rcItem.PtInRect(point))
464 {
465 m_nHoverTabItem = i;
466 break;
467 }
468 }
469 if (m_nHoverTabItem != nOldHover)
470 {
471 if (nOldHover != -1)
472 {
473 if (nOldHover != m_nCurrentPage)
474 {
475 GetItemRect(nOldHover, rcItem);
476 InvalidateRect(rcItem);
477 }
478 EventTabItemLeave evt(this);
479 evt.iLeave = nOldHover;
480 FireEvent(evt);
481 }
482 if (m_nHoverTabItem != -1)
483 {
485 {
487 InvalidateRect(rcItem);
488 }
489 EventTabItemHover evt(this);
490 evt.iHover = m_nHoverTabItem;
491 FireEvent(evt);
492 }
493 }
494}
495
497{
498 for (int i = GetItemCount() - 1; i >= 0; i--)
499 {
501 }
502 m_lstPages.RemoveAll();
503 __baseCls::OnDestroy();
504}
505
507{
508 if (iPage < 0 || iPage >= (int)GetItemCount())
509 return NULL;
510 return m_lstPages[iPage];
511}
512
513int STabCtrl::GetPageIndex(LPCTSTR pszName, BOOL bTitle)
514{
515 if (bTitle)
516 {
517 for (UINT i = 0; i < m_lstPages.GetCount(); i++)
518 {
519 if (_tcscmp(m_lstPages[i]->GetTitle(), pszName) == 0)
520 return i;
521 }
522 }
523 else
524 {
525 SStringW strName = S_CT2W(pszName);
526 for (UINT i = 0; i < m_lstPages.GetCount(); i++)
527 {
528 if (m_lstPages[i]->GetName() == strName)
529 return i;
530 }
531 }
532 return -1;
533}
534
535STabPage *STabCtrl::GetPage(LPCTSTR pszName, BOOL bTitle /*=TRUE*/)
536{
537 int iPage = GetPageIndex(pszName, bTitle);
538 if (iPage == -1)
539 return NULL;
540 return m_lstPages[iPage];
541}
542
543IWindow *STabCtrl::GetPage(int iPage)
544{
545 if (iPage < 0 || iPage >= GetItemCount())
546 return NULL;
547 return m_lstPages[iPage];
548}
549
550void STabCtrl::OnSliderFinish()
551{
552 SASSERT(m_tabSlider);
553 DestroyChild(m_tabSlider);
554 m_tabSlider = NULL;
555 STabPage *pPage = m_lstPages[m_nCurrentPage];
556 SASSERT(pPage);
557 pPage->SetVisible(TRUE, TRUE);
558}
559
560BOOL STabCtrl::SetCurSel(int nIndex)
561{
562 if (nIndex < 0 || nIndex > (int)GetItemCount() - 1 || (m_nCurrentPage == nIndex))
563 return FALSE;
564 int nOldPage = m_nCurrentPage;
565
566 EventTabSelChanging evt(this);
567 evt.bCancel = FALSE;
568 evt.uOldSel = nOldPage;
569 evt.uNewSel = nIndex;
570
571 FireEvent(evt);
572
573 if (evt.bCancel)
574 return FALSE;
575
576 CRect rcItem;
577
579 InvalidateRect(rcItem);
580
581 if (m_tabSlider)
582 {
583 m_tabSlider->Stop();
584 }
585 if (m_nAnimateSteps && IsVisible(TRUE) && nOldPage != -1 && nIndex != -1)
586 {
587 m_tabSlider = new STabSlider(this, nOldPage, nIndex, m_nAnimateSteps, m_nAniamteType, m_aniInterpolator);
588 }
589 else
590 {
591 if (nOldPage != -1)
592 {
593 GetItem(nOldPage)->SetVisible(FALSE, TRUE);
594 }
595 if (nIndex != -1)
596 {
597 GetItem(nIndex)->SetVisible(TRUE, TRUE);
598 }
599 }
600 m_nCurrentPage = nIndex;
602 InvalidateRect(rcItem);
603
604 EventTabSelChanged evt2(this);
605 evt2.uNewSel = nIndex;
606 evt2.uOldSel = nOldPage;
607
608 FireEvent(evt2);
609 return TRUE;
610}
611
612BOOL STabCtrl::SetCurSel(LPCTSTR pszName, BOOL bTitle /*=TRUE */)
613{
614 int iPage = GetPageIndex(pszName, bTitle);
615 if (iPage == -1)
616 return FALSE;
617 return SetCurSel(iPage);
618}
619
620BOOL STabCtrl::SetItemTitle(int nIndex, LPCTSTR lpszTitle)
621{
622 STabPage *pTab = GetItem(nIndex);
623 if (pTab)
624 {
625 pTab->SetTitle(lpszTitle);
626
627 CRect rcTitle = GetTitleRect();
628 InvalidateRect(rcTitle);
629 return TRUE;
630 }
631
632 return FALSE;
633}
634
636{
637 for (SXmlNode xmlChild = xmlNode.first_child(); xmlChild; xmlChild = xmlChild.next_sibling())
638 {
639 InsertItem(xmlChild, -1, TRUE);
640 }
641
642 if (m_nCurrentPage == -1 || m_nCurrentPage >= (int)m_lstPages.GetCount())
643 {
644 m_nCurrentPage = 0;
645 }
646 if (m_lstPages.GetCount() == 0)
647 {
648 m_nCurrentPage = -1;
649 }
650
651 if (m_nCurrentPage != -1)
652 {
653 GetItem(m_nCurrentPage)->SetVisible(TRUE);
654 }
655 return TRUE;
656}
657
658STabPage *STabCtrl::CreatePageFromXml(SXmlNode xmlPage)
659{
660 if (wcscmp(xmlPage.name(), STabPage::GetClassName()) != 0)
661 return NULL;
663}
664
665int STabCtrl::InsertItem(LPCWSTR lpContent, int iInsert /*=-1*/)
666{
667 SXmlDoc xmlDoc;
668 if (!xmlDoc.load_buffer(lpContent, wcslen(lpContent) * sizeof(wchar_t), xml_parse_default, sizeof(wchar_t) == 2 ? enc_utf16 : enc_utf32))
669 return -1;
670 return InsertItem(xmlDoc.root().first_child(), iInsert);
671}
672
673int STabCtrl::InsertItem(SXmlNode xmlNode, int iInsert /*=-1*/, BOOL bLoading /*=FALSE*/)
674{
675 if (_wcsicmp(xmlNode.name(), L"include") == 0)
676 { // support include tag
677 SStringT strSrc = S_CW2T(xmlNode.attribute(L"src").value());
678 SXmlDoc xmlDoc;
679 if (!LOADXML(xmlDoc, strSrc))
680 return NULL;
681 return InsertItem(xmlDoc.root().first_child(), iInsert, bLoading);
682 }
683 if (wcscmp(xmlNode.name(), STabPage::GetClassName()) != 0)
684 return NULL;
685 STabPage *pChild = CreatePageFromXml(xmlNode);
686 if (!pChild)
687 return -1;
688
689 InsertChild(pChild);
690 pChild->InitFromXml(&xmlNode);
691 pChild->GetLayoutParam()->SetMatchParent(Both);
692
693 if (iInsert == -1)
694 iInsert = (int)m_lstPages.GetCount();
695 m_lstPages.InsertAt(iInsert, pChild);
696
697 if (!bLoading)
698 {
699 CRect rcPage;
700 GetChildrenLayoutRect(&rcPage);
701 pChild->Move(&rcPage);
702 pChild->SetVisible(FALSE, FALSE);
703 if (m_nCurrentPage >= iInsert)
706 if (m_nCurrentPage == -1)
707 SetCurSel(iInsert);
708 }
709 OnItemInserted(pChild);
710 return iInsert;
711}
712
714{
715 CRect rcTitle;
716 GetClientRect(rcTitle);
717 switch (m_nTabAlign)
718 {
719 case AlignTop:
720 rcTitle.bottom = rcTitle.top + m_szTab[1].toPixelSize(GetScale());
721 break;
722 case AlignBottom:
723 rcTitle.top = rcTitle.bottom - m_szTab[1].toPixelSize(GetScale());
724 break;
725 case AlignLeft:
726 rcTitle.right = rcTitle.left + m_szTab[0].toPixelSize(GetScale());
727 break;
728 case AlignRight:
729 rcTitle.left = rcTitle.right - m_szTab[0].toPixelSize(GetScale());
730 break;
731 }
732 return rcTitle;
733}
734
735BOOL STabCtrl::GetItemRect(int nIndex, CRect &rcItem)
736{
737 if (nIndex < 0 || nIndex >= (int)GetItemCount())
738 return FALSE;
739
740 CRect rcTitle = GetTitleRect();
741
742 rcItem = CRect(rcTitle.TopLeft(), CSize(m_szTab[0].toPixelSize(GetScale()), m_szTab[1].toPixelSize(GetScale())));
743
744 switch (m_nTabAlign)
745 {
746 case AlignTop:
747 case AlignBottom:
748 rcItem.OffsetRect(m_nTabPos.toPixelSize(GetScale()) + nIndex * (rcItem.Width() + m_nTabInterSize.toPixelSize(GetScale())), 0);
749 break;
750 case AlignLeft:
751 case AlignRight:
752 rcItem.OffsetRect(0, m_nTabPos.toPixelSize(GetScale()) + nIndex * (rcItem.Height() + m_nTabInterSize.toPixelSize(GetScale())));
753 break;
754 }
755 rcItem.IntersectRect(rcItem, rcTitle);
756 return TRUE;
757}
758
759void STabCtrl::DrawItem(IRenderTarget *pRT, const CRect &rcItem, int iItem, DWORD dwState)
760{
761 if (rcItem.IsRectEmpty())
762 return;
763 if (m_pSkinTab)
764 m_pSkinTab->DrawByState(pRT, rcItem, dwState);
765 int iState = SState2Index::GetDefIndex(dwState, true);
766 //根据状态从style中获得字体,颜色
767 IFontPtr font = m_style.GetTextFont(iState);
768 COLORREF crTxt = m_style.GetTextColor(iState);
769 SAutoRefPtr<IFontS> oldFont;
770 if (font)
771 pRT->SelectObject(font, (IRenderObj **)&oldFont);
772 COLORREF crOld = 0;
773 if (crTxt != CR_INVALID)
774 crOld = pRT->SetTextColor(crTxt);
775
776 CRect rcIcon(CPoint(m_ptIcon[0].toPixelSize(GetScale()), m_ptIcon[1].toPixelSize(GetScale())) + rcItem.TopLeft(), CSize(0, 0));
777 if (m_pSkinIcon)
778 {
779 rcIcon.right = rcIcon.left + m_pSkinIcon->GetSkinSize().cx;
780 rcIcon.bottom = rcIcon.top + m_pSkinIcon->GetSkinSize().cy;
781 int iIcon = GetItem(iItem)->GetIconIndex();
782 if (iIcon == -1)
783 iIcon = iItem;
784 m_pSkinIcon->DrawByIndex(pRT, rcIcon, iIcon);
785 }
786
787 if (m_ptText[0].toPixelSize(GetScale()) > 0 && m_ptText[1].toPixelSize(GetScale()) > 0)
788 { //从指定位置开始绘制文字
789 if (m_txtDir == Text_Horz)
790 pRT->TextOut(rcItem.left + m_ptText[0].toPixelSize(GetScale()), rcItem.top + m_ptText[1].toPixelSize(GetScale()), GetItem(iItem)->GetTitle(), -1);
791 else
792 TextOutV(pRT, rcItem.left + m_ptText[0].toPixelSize(GetScale()), rcItem.top + m_ptText[1].toPixelSize(GetScale()), GetItem(iItem)->GetTitle());
793 }
794 else
795 {
796 CRect rcText = rcItem;
797 UINT alignStyle = m_style.GetTextAlign();
798 UINT align = alignStyle;
799 if (m_ptText[0].toPixelSize(GetScale()) < 0 && m_ptText[1].toPixelSize(GetScale()) > 0)
800 { //指定了Y偏移,X居中
801 rcText.top += m_ptText[1].toPixelSize(GetScale());
802 align = alignStyle & (DT_CENTER | DT_RIGHT | DT_SINGLELINE | DT_END_ELLIPSIS);
803 }
804 else if (m_ptText[0].toPixelSize(GetScale()) > 0 && m_ptText[1].toPixelSize(GetScale()) < 0)
805 { //指定了X偏移,Y居中
806 rcText.left += m_ptText[0].toPixelSize(GetScale());
807 align = alignStyle & (DT_VCENTER | DT_BOTTOM | DT_SINGLELINE | DT_END_ELLIPSIS);
808 }
809
810 if (m_txtDir == Text_Horz)
811 pRT->DrawText(GetItem(iItem)->GetTitle(), -1, &rcText, align);
812 else
813 DrawTextV(pRT, rcText, GetItem(iItem)->GetTitle());
814 }
815
816 //恢复字体,颜色
817 if (font)
818 pRT->SelectObject(oldFont, NULL);
819 if (crTxt != CR_INVALID)
820 pRT->SetTextColor(crOld);
821}
822
824{
825 int iItem = HitTest(pt);
826 if (iItem == -1)
827 return FALSE;
828 if (GetItem(iItem)->GetToolTipText().IsEmpty())
829 return FALSE;
830 tipInfo.swnd = m_swnd;
831 tipInfo.dwCookie = iItem;
832 GetItemRect(iItem, tipInfo.rcTarget);
833 tipInfo.strTip = GetItem(iItem)->GetToolTipText();
834 return TRUE;
835}
836
837void STabCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
838{
839 if (nChar == VK_LEFT || nChar == VK_UP)
840 {
841 if (!SetCurSel(m_nCurrentPage - 1))
842 SetCurSel(GetItemCount() - 1);
843 }
844 else if (nChar == VK_RIGHT || nChar == VK_DOWN)
845 {
846 if (!SetCurSel(m_nCurrentPage + 1))
847 SetCurSel(0);
848 }
849 else if (nChar == VK_HOME)
850 {
851 SetCurSel(0);
852 }
853 else if (nChar == VK_END)
854 {
855 SetCurSel(GetItemCount() - 1);
856 }
857}
858
859int STabCtrl::HitTest(CPoint pt)
860{
861 int nTabCount = GetItemCount();
862 for (int i = 0; i < nTabCount; i++)
863 {
864 CRect rcItem;
865 GetItemRect(i, rcItem);
866
867 if (rcItem.PtInRect(pt))
868 {
869 return i;
870 }
871 }
872 return -1;
873}
874
875void STabCtrl::OnInitFinished(THIS_ IXmlNode *xmlNode)
876{
877 if (m_pSkinTab)
878 {
879 SIZE sz = m_pSkinTab->GetSkinSize();
880 if (SLayoutSize::fequal(m_szTab[0].fSize, -1.f))
881 m_szTab[0] = SLayoutSize((float)sz.cx, SLayoutSize::defUnit);
882 if (SLayoutSize::fequal(m_szTab[1].fSize, -1.f))
883 m_szTab[1] = SLayoutSize((float)sz.cy, SLayoutSize::defUnit);
884 }
885}
886
888{
889 CRect rcPage;
890 GetChildrenLayoutRect(&rcPage);
891 for (size_t i = 0; i < m_lstPages.GetCount(); i++)
892 {
893 m_lstPages[i]->Move(rcPage);
894 }
895}
896
898{
899 IFontPtr pFont = m_style.GetTextFont(0);
900 if (pFont)
901 pRT->SelectObject(pFont, (IRenderObj **)&painter.oldFont);
902
903 COLORREF crTxt = m_style.GetTextColor(0);
904 if (crTxt != CR_INVALID)
905 painter.oldTextColor = pRT->SetTextColor(crTxt);
906}
907
908void STabCtrl::TextOutV(IRenderTarget *pRT, int x, int y, const SStringT &strText)
909{
910 SStringT strTmp = strText;
911 LPTSTR p = strTmp.GetBuffer(0);
912 while (*p)
913 {
914 LPTSTR p2 = SStringT::_tchar_traits::CharNext(p);
915 SIZE szWord;
916 pRT->MeasureText(p, (int)(p2 - p), &szWord);
917 pRT->TextOut(x, y, p, (int)(p2 - p));
918 p = p2;
919 y += szWord.cy;
920 }
921 strTmp.ReleaseBuffer();
922}
923
924SIZE STabCtrl::MeasureTextV(IRenderTarget *pRT, const SStringT &strText)
925{
926 SIZE szRet = { 0, 0 };
927 SStringT strTmp = strText;
928 LPTSTR p = strTmp.GetBuffer(0);
929 while (*p)
930 {
931 LPTSTR p2 = SStringT::_tchar_traits::CharNext(p);
932 SIZE szWord;
933 pRT->MeasureText(p, (int)(p2 - p), &szWord);
934 szRet.cx = smax(szRet.cx, szWord.cx);
935 szRet.cy += szWord.cy;
936 p = p2;
937 }
938 strTmp.ReleaseBuffer();
939
940 return szRet;
941}
942
943void STabCtrl::DrawTextV(IRenderTarget *pRT, CRect rcText, const SStringT &strText)
944{ // only support horizontal and vertical center
945 SIZE szText = MeasureTextV(pRT, strText);
946 TextOutV(pRT, rcText.left + (rcText.Width() - szText.cx) / 2, rcText.top + (rcText.Height() - szText.cy) / 2, strText);
947}
948
949void STabCtrl::OnColorize(COLORREF cr)
950{
951 __baseCls::OnColorize(cr);
952 if (m_pSkinIcon)
953 m_pSkinIcon->OnColorize(cr);
954 if (m_pSkinTab)
955 m_pSkinTab->OnColorize(cr);
956 if (m_pSkinTabInter)
957 m_pSkinTabInter->OnColorize(cr);
958 if (m_pSkinFrame)
959 m_pSkinFrame->OnColorize(cr);
960}
961
963{
964 __baseCls::OnScaleChanged(nScale);
965 if (m_pSkinIcon)
966 GetScaleSkin(m_pSkinIcon, nScale);
967 if (m_pSkinTab)
968 GetScaleSkin(m_pSkinTab, nScale);
969 if (m_pSkinTabInter)
971 if (m_pSkinFrame)
972 GetScaleSkin(m_pSkinFrame, nScale);
973}
974
976{
977 __baseCls::OnLanguageChanged();
978 for (int i = 0; i < (int)m_lstPages.GetCount(); i++)
979 {
980 STabPage *pPage = m_lstPages.GetAt(i);
981 pPage->m_strTitle.TranslateText();
982 }
984 return HRESULT(3);
985}
986
988{
989 return m_nCurrentPage;
990}
991
993{
994 return (int)m_lstPages.GetCount();
995}
996
997SNSEND
Definition of the STabCtrl and related classes.
@ WndState_Hover
Definition SWnd.h:76
@ WndState_Normal
Definition SWnd.h:75
@ WndState_PushDown
Definition SWnd.h:77
Smart pointer class for managing COM-style reference-counted objects.
布局大小类
Definition SLayoutSize.h:10
static bool fequal(float a, float b)
比较两个浮点数是否相等
LPCWSTR GetName() SCONST OVERRIDE
Definition Sobject.hpp:108
static LPCWSTR GetClassName()
Definition Sobject.hpp:41
Helper class for painting.
Definition SWnd.h:178
SAutoRefPtr< IFontS > oldFont
Definition SWnd.h:185
COLORREF oldTextColor
Definition SWnd.h:186
static SApplication & getSingleton(void)
Definition SSingleton.h:63
static int GetDefIndex(DWORD dwState, bool checkAsPushdown=false)
Gets the default index for a given state.
A class representing an ASCII string.
Definition sstringw.h:96
int m_nAniamteType
Definition STabCtrl.h:151
SAutoRefPtr< ISkinObj > m_pSkinTabInter
Definition STabCtrl.h:129
SLayoutSize m_szTab[2]
Definition STabCtrl.h:125
virtual void OnItemInserted(STabPage *pItem)
Handles the insertion of a tab page.
Definition STabCtrl.h:276
void UpdateChildrenPosition() OVERRIDE
Updates the positions of child windows.
Definition STabCtrl.cpp:887
STabPage * GetItem(int iPage)
Gets a tab page by index.
Definition STabCtrl.cpp:506
BOOL SetCurSel(int nIndex) OVERRIDE
Sets the currently selected tab page.
Definition STabCtrl.cpp:560
virtual void OnItemRemoved(STabPage *pItem)
Handles the removal of a tab page.
Definition STabCtrl.h:284
SIZE MeasureTextV(IRenderTarget *pRT, const SStringT &strText)
Measures text vertically.
Definition STabCtrl.cpp:924
BOOL CreateChildren(SXmlNode xmlNode)
Creates tab pages from an XML node.
Definition STabCtrl.cpp:635
void OnDestroy()
Handles the destroy event.
Definition STabCtrl.cpp:496
virtual void OnColorize(COLORREF cr)
Adjusts the color tone of the window.
Definition STabCtrl.cpp:949
virtual HRESULT OnLanguageChanged()
Called when the language of the window changes.
Definition STabCtrl.cpp:975
int m_nAnimateSteps
Definition STabCtrl.h:150
int m_nCurrentPage
Definition STabCtrl.h:123
SAutoRefPtr< ISkinObj > m_pSkinFrame
Definition STabCtrl.h:130
int GetCurSel() SCONST OVERRIDE
Gets the index of the currently selected tab page.
Definition STabCtrl.cpp:987
int m_nHoverTabItem
Definition STabCtrl.h:122
void TextOutV(IRenderTarget *pRT, int x, int y, const SStringT &strText)
Outputs text vertically.
Definition STabCtrl.cpp:908
SArray< STabPage * > m_lstPages
Definition STabCtrl.h:135
int GetItemCount() SCONST OVERRIDE
Gets the number of tab pages.
Definition STabCtrl.cpp:992
void RemoveAllItems() OVERRIDE
Removes all tab pages.
Definition STabCtrl.cpp:440
STabCtrl()
Constructor for STabCtrl.
Definition STabCtrl.cpp:286
SAutoRefPtr< ISkinObj > m_pSkinIcon
Definition STabCtrl.h:128
int HitTest(CPoint pt)
Performs a hit test on the tab control.
Definition STabCtrl.cpp:859
int GetPageIndex(LPCTSTR pszName, BOOL bTitle) OVERRIDE
Gets the index of a tab page by name or title.
Definition STabCtrl.cpp:513
virtual CRect GetTitleRect()
Gets the rectangle of the tab header.
Definition STabCtrl.cpp:713
virtual BOOL GetItemRect(int nIndex, CRect &rcItem)
Gets the rectangle of a specified tab item.
Definition STabCtrl.cpp:735
void GetChildrenLayoutRect(RECT *prc) SCONST OVERRIDE
Gets the layout rectangle for child windows.
Definition STabCtrl.cpp:380
void DrawTextV(IRenderTarget *pRT, CRect rcText, const SStringT &strText)
Draws text vertically.
Definition STabCtrl.cpp:943
IWindow * GetPage(int nIndex) OVERRIDE
Gets a tab page by index.
Definition STabCtrl.cpp:543
virtual void OnScaleChanged(int nScale)
Called when the scale of the window changes.
Definition STabCtrl.cpp:962
BOOL RemoveItem(int nIndex, int iSelPage=0) OVERRIDE
Removes a tab page by index.
Definition STabCtrl.cpp:413
virtual void BeforePaint(IRenderTarget *pRT, SPainter &painter)
Prepares the rendering target for painting the current window.
Definition STabCtrl.cpp:897
void OnMouseMove(UINT nFlags, CPoint point)
Handles the mouse move event.
Definition STabCtrl.cpp:453
SLayoutSize m_nTabInterSize
Definition STabCtrl.h:124
void OnLButtonDown(UINT nFlags, CPoint point)
Handles the left mouse button down event.
Definition STabCtrl.cpp:403
int InsertItem(LPCWSTR lpContent, int iInsert=-1) OVERRIDE
Inserts a new tab page.
Definition STabCtrl.cpp:665
SLayoutSize m_ptText[2]
Definition STabCtrl.h:132
SLayoutSize m_nTabPos
Definition STabCtrl.h:126
BOOL SetItemTitle(int nIndex, LPCTSTR lpszTitle) OVERRIDE
Sets the title of a tab page.
Definition STabCtrl.cpp:620
virtual void DrawItem(IRenderTarget *pRT, const CRect &rcItem, int iItem, DWORD dwState)
Draws a tab item.
Definition STabCtrl.cpp:759
virtual BOOL UpdateToolTip(CPoint pt, SwndToolTipInfo &tipInfo)
Handle tooltip updates.
Definition STabCtrl.cpp:823
void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
Handles the key down event.
Definition STabCtrl.cpp:837
SAutoRefPtr< ISkinObj > m_pSkinTab
Definition STabCtrl.h:127
int m_nTabAlign
Definition STabCtrl.h:133
void OnPaint(IRenderTarget *pRT)
Handles the paint event.
Definition STabCtrl.cpp:314
SLayoutSize m_ptIcon[2]
Definition STabCtrl.h:131
A tab page within a tab control.
Definition STabCtrl.h:28
STrText m_strTitle
Definition STabCtrl.h:105
void SetTitle(LPCTSTR lpszTitle) OVERRIDE
Sets the title of the tab page.
Definition STabCtrl.h:64
void TranslateText()
Translates the text.
Definition Swnd.cpp:42
Base class for SOUI DUI windows.
Definition SWnd.h:286
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Fires an event.
Definition Swnd.cpp:1540
BOOL DestroyChild(SWindow *pChild)
Destroys a child window.
Definition Swnd.cpp:519
virtual void OnContainerChanged(ISwndContainer *pOldContainer, ISwndContainer *pNewContainer)
Called when the container of the window changes.
Definition Swnd.cpp:3407
SWindow * GetParent() const
Retrieves the parent window.
Definition Swnd.cpp:3488
void SetVisible(BOOL bVisible, BOOL bUpdate=FALSE) OVERRIDE
Sets the visibility of the window.
Definition Swnd.cpp:655
void OnDestroy()
Handles the destruction of the window.
Definition Swnd.cpp:1701
SwndStyle m_style
Definition SWnd.h:2596
int GetScale() SCONST OVERRIDE
Retrieves the scale factor of the window.
Definition Swnd.cpp:3266
CRect GetWindowRect() const
Retrieves the bounding rectangle of the window.
Definition Swnd.cpp:230
BOOL IsVisible(BOOL bCheckParent=FALSE) SCONST OVERRIDE
Checks if the window is visible.
Definition Swnd.cpp:646
void PaintForeground(IRenderTarget *pRT, LPRECT pRc, SWindow *pStartFrom=NULL)
Draws the foreground content of the window.
Definition Swnd.cpp:2694
ISwndContainer * GetContainer() OVERRIDE
Retrieves the container associated with this window.
Definition Swnd.cpp:679
BOOL IsFocused() SCONST OVERRIDE
Checks if the window has focus.
Definition Swnd.cpp:2639
void PaintBackground(IRenderTarget *pRT, LPRECT pRc)
Draws the background content of the window.
Definition Swnd.cpp:2673
void GetChildrenLayoutRect(RECT *prc) SCONST OVERRIDE
Retrieves the layout rectangle of the children.
Definition Swnd.cpp:2181
BOOL m_bDrawFocusRect
Definition SWnd.h:2610
void OnSize(UINT nType, CSize size)
Handles the resizing of the window.
Definition Swnd.cpp:2844
virtual CRect GetClientRect() const
Retrieves the client rectangle of the window.
Definition Swnd.cpp:243
void InsertChild(SWindow *pNewChild, SWindow *pInsertAfter=NULL)
Inserts a child window into the window tree.
Definition Swnd.cpp:538
SWindow * GetRoot() const
Retrieves the root window in the hierarchy.
Definition Swnd.cpp:3493
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
void UpdateLayout() OVERRIDE
Updates the layout of the window.
Definition Swnd.cpp:2251
BOOL m_bFocusable
Definition SWnd.h:2609
virtual SWindow * CreateChildByName(LPCWSTR pszName)
Create child window by name.
Definition Swnd.cpp:935
SWindow()
Constructor.
Definition Swnd.cpp:104
void OnLButtonDown(UINT nFlags, CPoint pt)
Handles the left mouse button down event.
Definition Swnd.cpp:2092
virtual void AfterPaint(IRenderTarget *pRT, SPainter &painter)
Restore rendering environment.
Definition Swnd.cpp:1776
ILayoutParam * GetLayoutParam() SCONST OVERRIDE
Retrieves the layout parameter object associated with the window.
Definition SWnd.h:405
void DrawDefFocusRect(IRenderTarget *pRT, CRect rc)
Draws the default focus rectangle.
Definition Swnd.cpp:1981
BOOL IsFocusable() SCONST OVERRIDE
Checks if the window is focusable.
Definition Swnd.cpp:1996
void Invalidate() OVERRIDE
Invalidates the entire window.
Definition Swnd.cpp:1437
SEventSet m_evtSet
Definition SWnd.h:2581
virtual SStringT GetToolTipText()
Retrieves the tooltip text of the window.
Definition Swnd.cpp:3236
void GetScaleSkin(SAutoRefPtr< ISkinObj > &pSkin, int nScale)
Retrieves a scaled skin object based on the current scale factor.
Definition Swnd.cpp:3290
BOOL InitFromXml(IXmlNode *pNode) OVERRIDE
Initializes the window from an XML node.
Definition Swnd.cpp:946
const SwndStyle & GetStyle() const
Retrieves the style of the window.
Definition Swnd.cpp:716
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
const wchar_t * value() const
Gets the attribute value.
Definition SXml.cpp:90
Implementation of IXmlDoc.
Definition SXml.h:912
SXmlNode root() const
Retrieves the root node of the document.
Definition SXml.cpp:754
bool load_buffer(const void *contents, size_t size, unsigned int options=xml_parse_default, XmlEncoding encoding=enc_auto)
Loads the document from a buffer.
Definition SXml.cpp:726
Class representing an XML node.
Definition SXml.h:352
SXmlNode next_sibling() const
Gets the next sibling node in the children list of the parent node.
Definition SXml.cpp:393
SXmlNode first_child() const
Gets the first child node of the node.
Definition SXml.cpp:383
const wchar_t * name() const
Gets the name of the node.
Definition SXml.cpp:363
SXmlAttr attribute(const wchar_t *name, bool bCaseSensitive=false) const
Gets the attribute with the specified name.
Definition SXml.cpp:428
Base class for all renderable objects.
Definition SRender-i.h:145
Interface for rendering target objects.
Definition SRender-i.h:1440
HRESULT DrawText(LPCTSTR pszText, int cchLen, LPRECT pRc, UINT uFormat) PURE
Draw text within a rectangle.
HRESULT AlphaBlend(LPCRECT pRcDest, IRenderTarget *pRTSrc, LPCRECT pRcSrc, BYTE byAlpha) PURE
Performs an alpha-blended transfer from one render target to another.
HRESULT SelectObject(IRenderObj *pObj, IRenderObj **pOldObj=NULL) PURE
Selects a new rendering object and optionally retrieves the previous one.
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 TextOut(int x, int y, LPCTSTR lpszString, int nCount) PURE
Output text at a specified position.
COLORREF SetTextColor(COLORREF color) PURE
Sets the current text color.
HRESULT MeasureText(LPCTSTR pszText, int cchLen, SIZE *psz) PURE
Measure the size of the text.
BOOL RegisterTimelineHandler(ITimelineHandler *pHandler) PURE
Registers an animation frame handler.
BOOL UnregisterTimelineHandler(ITimelineHandler *pHandler) PURE
Unregisters an animation frame handler.
时间轴处理接口
Interface for XML nodes.
Definition sxml-i.h:128
Information for window tooltips.
Definition SWnd.h:208
CRect rcTarget
Definition SWnd.h:211
DWORD dwCookie
Definition SWnd.h:210
SStringT strTip
Definition SWnd.h:212