tb_tab_container.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. PreferredSize TBTabLayout::OnCalculatePreferredContentSize(const SizeConstraints &constraints)
  19. {
  20. PreferredSize ps = TBLayout::OnCalculatePreferredContentSize(constraints);
  21. // Make sure the number of tabs doesn't grow parents.
  22. // It is only the content that should do that. The tabs
  23. // will scroll anyway.
  24. if (GetAxis() == AXIS_X)
  25. ps.min_w = MIN(ps.min_w, 1);
  26. else
  27. ps.min_h = MIN(ps.min_h, 1);
  28. return ps;
  29. }
  30. // == TBTabContainer ====================================================================
  31. TBTabContainer::TBTabContainer()
  32. : m_need_page_update(true)
  33. , m_current_page(-1)
  34. , m_align(TB_ALIGN_TOP)
  35. {
  36. AddChild(&m_root_layout);
  37. // Put the tab layout on top of the content in Z order so their skin can make
  38. // a seamless overlap over the border. Control which side they are layouted
  39. // to by calling SetLayoutOrder.
  40. m_root_layout.AddChild(&m_content_root);
  41. m_root_layout.AddChild(&m_tab_layout);
  42. m_root_layout.SetAxis(AXIS_Y);
  43. m_root_layout.SetGravity(WIDGET_GRAVITY_ALL);
  44. m_root_layout.SetLayoutDistribution(LAYOUT_DISTRIBUTION_AVAILABLE);
  45. m_root_layout.SetLayoutOrder(LAYOUT_ORDER_TOP_TO_BOTTOM);
  46. m_root_layout.SetSkinBg(TBIDC("TBTabContainer.rootlayout"));
  47. m_tab_layout.SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_CENTER);
  48. m_tab_layout.SetSkinBg(TBIDC("TBTabContainer.tablayout_x"));
  49. m_tab_layout.SetLayoutPosition(LAYOUT_POSITION_RIGHT_BOTTOM);
  50. m_content_root.SetGravity(WIDGET_GRAVITY_ALL);
  51. m_content_root.SetSkinBg(TBIDC("TBTabContainer.container"));
  52. }
  53. TBTabContainer::~TBTabContainer()
  54. {
  55. m_root_layout.RemoveChild(&m_content_root);
  56. m_root_layout.RemoveChild(&m_tab_layout);
  57. RemoveChild(&m_root_layout);
  58. }
  59. void TBTabContainer::SetAxis(AXIS axis)
  60. {
  61. m_root_layout.SetAxis(axis);
  62. m_tab_layout.SetAxis(axis == AXIS_X ? AXIS_Y : AXIS_X);
  63. m_tab_layout.SetSkinBg(axis == AXIS_X ? TBIDC("TBTabContainer.tablayout_y") :
  64. TBIDC("TBTabContainer.tablayout_x"));
  65. }
  66. void TBTabContainer::SetValue(int index)
  67. {
  68. if (index == m_current_page || !GetNumPages())
  69. return;
  70. m_current_page = index;
  71. // Update the pages visibility and tabs pressed value.
  72. index = 0;
  73. TBWidget *page = m_content_root.GetFirstChild();
  74. TBWidget *tab = m_tab_layout.GetFirstChild();
  75. for ( ; page && tab; page = page->GetNext(), tab = tab->GetNext(), index++)
  76. {
  77. bool active = index == m_current_page;
  78. page->SetVisibilility(active ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
  79. tab->SetValue(active ? 1 : 0);
  80. }
  81. TBWidgetEvent ev(EVENT_TYPE_TAB_CHANGED);
  82. InvokeEvent(ev);
  83. }
  84. int TBTabContainer::GetNumPages()
  85. {
  86. int count = 0;
  87. for (TBWidget *tab = m_tab_layout.GetFirstChild(); tab; tab = tab->GetNext())
  88. count++;
  89. if (!count)
  90. m_current_page = -1;
  91. return count;
  92. }
  93. TBWidget *TBTabContainer::GetCurrentPageWidget() const
  94. {
  95. if (m_current_page == -1)
  96. return nullptr;
  97. return m_content_root.GetChildFromIndex(m_current_page);
  98. }
  99. void TBTabContainer::SetAlignment(TB_ALIGN align)
  100. {
  101. bool horizontal = (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM);
  102. bool reverse = (align == TB_ALIGN_TOP || align == TB_ALIGN_LEFT);
  103. SetAxis(horizontal ? AXIS_Y : AXIS_X);
  104. m_root_layout.SetLayoutOrder(reverse ? LAYOUT_ORDER_TOP_TO_BOTTOM : LAYOUT_ORDER_BOTTOM_TO_TOP);
  105. m_tab_layout.SetLayoutPosition(reverse ? LAYOUT_POSITION_RIGHT_BOTTOM : LAYOUT_POSITION_LEFT_TOP);
  106. m_align = align;
  107. }
  108. bool TBTabContainer::OnEvent(const TBWidgetEvent &ev)
  109. {
  110. if ((ev.type == EVENT_TYPE_CLICK || ev.type == EVENT_TYPE_POINTER_DOWN) &&
  111. ev.target->GetID() == TBIDC("tab") &&
  112. ev.target->GetParent() == &m_tab_layout)
  113. {
  114. int clicked_index = m_tab_layout.GetIndexFromChild(ev.target);
  115. SetValue(clicked_index);
  116. return true;
  117. }
  118. return false;
  119. }
  120. void TBTabContainer::OnProcess()
  121. {
  122. if (m_need_page_update)
  123. {
  124. m_need_page_update = false;
  125. // Force update value
  126. int current_page = m_current_page;
  127. m_current_page = -1;
  128. SetValue(current_page);
  129. }
  130. }
  131. }; // namespace tb