tb_tab_container.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #include "tb_tab_container.h"
  6. #include <assert.h>
  7. namespace tb {
  8. // == TBTabLayout =======================================================================
  9. void TBTabLayout::OnChildAdded(TBWidget *child)
  10. {
  11. if (TBButton *button = TBSafeCast<TBButton>(child))
  12. {
  13. button->SetSqueezable(true);
  14. button->SetSkinBg(TBIDC("TBTabContainer.tab"));
  15. button->SetID(TBIDC("tab"));
  16. }
  17. }
  18. void TBTabLayout::OnChildRemove(TBWidget *child)
  19. {
  20. int index = GetIndexFromChild(child);
  21. if (index < tabContainer_->m_current_page)
  22. --tabContainer_->m_current_page;
  23. }
  24. PreferredSize TBTabLayout::OnCalculatePreferredContentSize(const SizeConstraints &constraints)
  25. {
  26. PreferredSize ps = TBLayout::OnCalculatePreferredContentSize(constraints);
  27. // Make sure the number of tabs doesn't grow parents.
  28. // It is only the content that should do that. The tabs
  29. // will scroll anyway.
  30. if (GetAxis() == AXIS_X)
  31. ps.min_w = MIN(ps.min_w, 1);
  32. else
  33. ps.min_h = MIN(ps.min_h, 1);
  34. return ps;
  35. }
  36. // == TBTabContainer ====================================================================
  37. TBTabContainer::TBTabContainer()
  38. : m_need_page_update(true)
  39. , m_current_page(-1)
  40. , m_align(TB_ALIGN_TOP)
  41. , m_tab_layout(this)
  42. {
  43. AddChild(&m_root_layout);
  44. // Put the tab layout on top of the content in Z order so their skin can make
  45. // a seamless overlap over the border. Control which side they are layouted
  46. // to by calling SetLayoutOrder.
  47. m_root_layout.AddChild(&m_content_root);
  48. m_root_layout.AddChild(&m_tab_layout);
  49. m_root_layout.SetAxis(AXIS_Y);
  50. m_root_layout.SetGravity(WIDGET_GRAVITY_ALL);
  51. m_root_layout.SetLayoutDistribution(LAYOUT_DISTRIBUTION_AVAILABLE);
  52. m_root_layout.SetLayoutOrder(LAYOUT_ORDER_TOP_TO_BOTTOM);
  53. m_root_layout.SetSkinBg(TBIDC("TBTabContainer.rootlayout"));
  54. m_root_layout.SetID("root_layout");
  55. m_tab_layout.SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_CENTER);
  56. m_tab_layout.SetSkinBg(TBIDC("TBTabContainer.tablayout_x"));
  57. m_tab_layout.SetLayoutPosition(LAYOUT_POSITION_RIGHT_BOTTOM);
  58. m_tab_layout.SetID("tab_layout");
  59. m_content_root.SetGravity(WIDGET_GRAVITY_ALL);
  60. m_content_root.SetSkinBg(TBIDC("TBTabContainer.container"));
  61. m_content_root.SetID("content_root");
  62. }
  63. TBTabContainer::~TBTabContainer()
  64. {
  65. m_root_layout.RemoveChild(&m_content_root);
  66. m_root_layout.RemoveChild(&m_tab_layout);
  67. RemoveChild(&m_root_layout);
  68. }
  69. void TBTabContainer::SetAxis(AXIS axis)
  70. {
  71. m_root_layout.SetAxis(axis);
  72. m_tab_layout.SetAxis(axis == AXIS_X ? AXIS_Y : AXIS_X);
  73. m_tab_layout.SetSkinBg(axis == AXIS_X ? TBIDC("TBTabContainer.tablayout_y") :
  74. TBIDC("TBTabContainer.tablayout_x"));
  75. }
  76. void TBTabContainer::SetValue(int index)
  77. {
  78. if (index == m_current_page || !GetNumPages())
  79. return;
  80. m_current_page = index;
  81. // Update the pages visibility and tabs pressed value.
  82. index = 0;
  83. TBWidget *page = m_content_root.GetFirstChild();
  84. TBWidget *tab = m_tab_layout.GetFirstChild();
  85. for ( ; page && tab; page = page->GetNext(), tab = tab->GetNext(), index++)
  86. {
  87. bool active = index == m_current_page;
  88. page->SetVisibilility(active ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
  89. tab->SetValue(active ? 1 : 0);
  90. if (active)
  91. {
  92. if (page->GetVisibility() == WIDGET_VISIBILITY_GONE)
  93. continue;
  94. TBRect contentRect = m_content_root.GetRect();
  95. TBSkinElement* skin = m_content_root.GetSkinBgElement();
  96. contentRect = contentRect.Shrink(skin->padding_left, skin->padding_top, skin->padding_right, skin->padding_bottom);
  97. TBRect pageRect = page->GetRect();
  98. if (contentRect.w != pageRect.w || contentRect.h != pageRect.h)
  99. {
  100. contentRect.x = skin->padding_left;
  101. contentRect.y = skin->padding_right;
  102. page->SetRect(contentRect);
  103. }
  104. }
  105. }
  106. TBWidgetEvent ev(EVENT_TYPE_TAB_CHANGED);
  107. InvokeEvent(ev);
  108. }
  109. int TBTabContainer::GetNumPages()
  110. {
  111. int count = 0;
  112. for (TBWidget *tab = m_tab_layout.GetFirstChild(); tab; tab = tab->GetNext())
  113. count++;
  114. if (!count)
  115. m_current_page = -1;
  116. return count;
  117. }
  118. TBWidget *TBTabContainer::GetCurrentPageWidget() const
  119. {
  120. if (m_current_page == -1)
  121. return nullptr;
  122. return m_content_root.GetChildFromIndex(m_current_page);
  123. }
  124. void TBTabContainer::SetAlignment(TB_ALIGN align)
  125. {
  126. bool horizontal = (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM);
  127. bool reverse = (align == TB_ALIGN_TOP || align == TB_ALIGN_LEFT);
  128. SetAxis(horizontal ? AXIS_Y : AXIS_X);
  129. m_root_layout.SetLayoutOrder(reverse ? LAYOUT_ORDER_TOP_TO_BOTTOM : LAYOUT_ORDER_BOTTOM_TO_TOP);
  130. m_tab_layout.SetLayoutPosition(reverse ? LAYOUT_POSITION_RIGHT_BOTTOM : LAYOUT_POSITION_LEFT_TOP);
  131. m_align = align;
  132. }
  133. bool TBTabContainer::OnEvent(const TBWidgetEvent &ev)
  134. {
  135. if ((ev.type == EVENT_TYPE_CLICK || ev.type == EVENT_TYPE_POINTER_DOWN) &&
  136. ev.target->GetID() == TBIDC("tab") &&
  137. ev.target->GetParent() == &m_tab_layout)
  138. {
  139. int clicked_index = m_tab_layout.GetIndexFromChild(ev.target);
  140. SetValue(clicked_index);
  141. return true;
  142. }
  143. return false;
  144. }
  145. void TBTabContainer::OnProcess()
  146. {
  147. if (m_need_page_update)
  148. {
  149. m_need_page_update = false;
  150. // Force update value
  151. int current_page = m_current_page;
  152. m_current_page = -1;
  153. SetValue(current_page);
  154. }
  155. }
  156. }; // namespace tb