TabControl.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. GWEN
  3. Copyright (c) 2010 Facepunch Studios
  4. See license in Gwen.h
  5. */
  6. #include "Gwen/Gwen.h"
  7. #include "Gwen/Skin.h"
  8. #include "Gwen/Controls/TabControl.h"
  9. #include "Gwen/Controls/Highlight.h"
  10. #include "Gwen/DragAndDrop.h"
  11. #include "Gwen/Controls/WindowControl.h"
  12. #include "Gwen/Controls/ScrollBarButton.h"
  13. namespace Gwen
  14. {
  15. namespace Controls
  16. {
  17. class TabControlInner : public Base
  18. {
  19. public:
  20. GWEN_CONTROL_INLINE( TabControlInner, Base )
  21. {
  22. m_ButtonRect = Gwen::Rect( 0, 0, 0, 0 );
  23. }
  24. void Render( Skin::Base* skin )
  25. {
  26. skin->DrawTabControl( this, m_ButtonRect );
  27. }
  28. void UpdateCurrentButton( Gwen::Rect rct )
  29. {
  30. m_ButtonRect = rct;
  31. }
  32. Gwen::Rect m_ButtonRect;
  33. };
  34. };
  35. };
  36. using namespace Gwen;
  37. using namespace Gwen::Controls;
  38. GWEN_CONTROL_CONSTRUCTOR( TabControl )
  39. {
  40. m_iScrollOffset = 0;
  41. m_pCurrentButton = NULL;
  42. m_TabStrip = new TabStrip( this );
  43. m_TabStrip->Dock( Pos::Top );
  44. m_TabStrip->SetWidth( 100 );
  45. m_TabStrip->SetHeight( 20 );
  46. // Make this some special control?
  47. m_pScroll[0] = new ControlsInternal::ScrollBarButton( this );
  48. m_pScroll[0]->SetDirectionLeft();
  49. m_pScroll[0]->onPress.Add( this, &TabControl::ScrollPressLeft );
  50. m_pScroll[0]->SetSize( 14, 16 );
  51. m_pScroll[1] = new ControlsInternal::ScrollBarButton( this );
  52. m_pScroll[1]->SetDirectionRight();
  53. m_pScroll[1]->onPress.Add( this, &TabControl::ScrollPressRight );
  54. m_pScroll[1]->SetSize( 14, 16 );
  55. m_InnerPanel = new TabControlInner( this );
  56. m_InnerPanel->Dock( Pos::Fill );
  57. SetTabable( false );
  58. }
  59. TabButton* TabControl::AddPage( const UnicodeString& strText, Controls::Base* pPage )
  60. {
  61. if ( !pPage )
  62. {
  63. pPage = new Base( this );
  64. }
  65. else
  66. {
  67. pPage->SetParent( this );
  68. }
  69. TabButton* pButton = new TabButton( m_TabStrip );
  70. pButton->SetText( strText );
  71. pButton->SetPage( pPage );
  72. pButton->SetTabable( false );
  73. AddPage( pButton );
  74. return pButton;
  75. }
  76. void TabControl::AddPage( TabButton* pButton )
  77. {
  78. Base* pPage = pButton->GetPage();
  79. pPage->SetParent( this );
  80. pPage->SetHidden( true );
  81. pPage->SetMargin( Margin( 6, 6, 6, 6 ) );
  82. pPage->Dock( Pos::Fill );
  83. pButton->SetParent( m_TabStrip );
  84. pButton->Dock( Pos::Left );
  85. pButton->SizeToContents();
  86. if ( pButton->GetTabControl() ) pButton->onPress.RemoveHandler( pButton->GetTabControl() );
  87. pButton->SetTabControl( this );
  88. pButton->onPress.Add( this, &TabControl::OnTabPressed );
  89. if ( !m_pCurrentButton )
  90. {
  91. pButton->OnPress();
  92. }
  93. onAddTab.Call( this );
  94. Invalidate();
  95. }
  96. void TabControl::OnTabPressed( Controls::Base* control )
  97. {
  98. if (!control)
  99. return;
  100. TabButton* pButton = control->DynamicCastTabButton();
  101. if ( !pButton ) return;
  102. Base* pPage = pButton->GetPage();
  103. if ( !pPage ) return;
  104. if ( m_pCurrentButton == pButton)
  105. return;
  106. if ( m_pCurrentButton )
  107. {
  108. Base* pPage = m_pCurrentButton->GetPage();
  109. if ( pPage )
  110. {
  111. pPage->SetHidden( true );
  112. }
  113. m_pCurrentButton = NULL;
  114. }
  115. m_pCurrentButton = pButton;
  116. pPage->SetHidden( false );
  117. m_TabStrip->Invalidate();
  118. Invalidate();
  119. }
  120. void TabControl::PostLayout( Skin::Base* skin )
  121. {
  122. BaseClass::PostLayout( skin );
  123. HandleOverflow();
  124. if ( m_TabStrip->Hidden() )
  125. {
  126. m_InnerPanel->DynamicCastTabControlInner()->UpdateCurrentButton( Gwen::Rect( 0, 0, 0, 0 ) );
  127. }
  128. else if ( m_pCurrentButton )
  129. {
  130. Gwen::Rect rct;
  131. Gwen::Point p = m_pCurrentButton->LocalPosToCanvas( Gwen::Point( 0, 0 ) );
  132. p = m_InnerPanel->CanvasPosToLocal( p );
  133. rct = Gwen::Rect( p.x+1, p.y+1, m_pCurrentButton->Width()-2, m_pCurrentButton->Height()-2 );
  134. m_InnerPanel->DynamicCastTabControlInner()->UpdateCurrentButton( rct );
  135. }
  136. }
  137. void TabControl::OnLoseTab( TabButton* pButton )
  138. {
  139. if ( m_pCurrentButton == pButton )
  140. m_pCurrentButton = NULL;
  141. //TODO: Select a tab if any exist.
  142. onLoseTab.Call( this );
  143. Invalidate();
  144. }
  145. int TabControl::TabCount( void )
  146. {
  147. return m_TabStrip->NumChildren();
  148. }
  149. void TabControl::SetTabStripPosition( int iDock )
  150. {
  151. m_TabStrip->SetTabPosition( iDock );
  152. }
  153. bool TabControl::DoesAllowDrag()
  154. {
  155. return m_TabStrip->AllowsTabReorder();
  156. }
  157. void TabControl::HandleOverflow()
  158. {
  159. Gwen::Point TabsSize = m_TabStrip->ChildrenSize();
  160. // Only enable the scrollers if the tabs are at the top.
  161. // This is a limitation we should explore.
  162. // Really TabControl should have derivitives for tabs placed elsewhere where we could specialize
  163. // some functions like this for each direction.
  164. bool bNeeded = TabsSize.x > Width() && m_TabStrip->GetDock() == Pos::Top;
  165. m_pScroll[0]->SetHidden( !bNeeded );
  166. m_pScroll[1]->SetHidden( !bNeeded );
  167. if ( !bNeeded ) return;
  168. m_iScrollOffset = Gwen::Clamp( m_iScrollOffset, 0, TabsSize.x - Width() + 32 );
  169. #if 0
  170. //
  171. // This isn't frame rate independent.
  172. // Could be better. Get rid of m_iScrollOffset and just use m_TabStrip->GetMargin().left ?
  173. // Then get a margin animation type and do it properly!
  174. // TODO!
  175. //
  176. m_TabStrip->SetMargin( Margin( Gwen::Approach( m_TabStrip->GetMargin().left, m_iScrollOffset * -1, 2 ), 0, 0, 0 ) );
  177. InvalidateParent();
  178. #else
  179. m_TabStrip->SetMargin( Margin( m_iScrollOffset * -1, 0, 0, 0 ) );
  180. #endif
  181. m_pScroll[0]->SetPos( Width() - 30 , 5 );
  182. m_pScroll[1]->SetPos( m_pScroll[0]->Right(), 5 );
  183. }
  184. void TabControl::ScrollPressLeft( Base* pFrom )
  185. {
  186. m_iScrollOffset -= 120;
  187. }
  188. void TabControl::ScrollPressRight( Base* pFrom )
  189. {
  190. m_iScrollOffset += 120;
  191. }