123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /*
- GWEN
- Copyright (c) 2010 Facepunch Studios
- See license in Gwen.h
- */
- #include "Gwen/Gwen.h"
- #include "Gwen/Skin.h"
- #include "Gwen/Controls/TabControl.h"
- #include "Gwen/Controls/Highlight.h"
- #include "Gwen/DragAndDrop.h"
- #include "Gwen/Controls/WindowControl.h"
- #include "Gwen/Controls/ScrollBarButton.h"
- namespace Gwen
- {
- namespace Controls
- {
- class TabControlInner : public Base
- {
- public:
- GWEN_CONTROL_INLINE( TabControlInner, Base )
- {
- m_ButtonRect = Gwen::Rect( 0, 0, 0, 0 );
- }
- void Render( Skin::Base* skin )
- {
- skin->DrawTabControl( this, m_ButtonRect );
- }
- void UpdateCurrentButton( Gwen::Rect rct )
- {
- m_ButtonRect = rct;
- }
- Gwen::Rect m_ButtonRect;
- };
- };
- };
- using namespace Gwen;
- using namespace Gwen::Controls;
- GWEN_CONTROL_CONSTRUCTOR( TabControl )
- {
- m_iScrollOffset = 0;
- m_pCurrentButton = NULL;
- m_TabStrip = new TabStrip( this );
- m_TabStrip->Dock( Pos::Top );
- m_TabStrip->SetWidth( 100 );
- m_TabStrip->SetHeight( 20 );
- // Make this some special control?
- m_pScroll[0] = new ControlsInternal::ScrollBarButton( this );
- m_pScroll[0]->SetDirectionLeft();
- m_pScroll[0]->onPress.Add( this, &TabControl::ScrollPressLeft );
- m_pScroll[0]->SetSize( 14, 16 );
- m_pScroll[1] = new ControlsInternal::ScrollBarButton( this );
- m_pScroll[1]->SetDirectionRight();
- m_pScroll[1]->onPress.Add( this, &TabControl::ScrollPressRight );
- m_pScroll[1]->SetSize( 14, 16 );
- m_InnerPanel = new TabControlInner( this );
- m_InnerPanel->Dock( Pos::Fill );
- SetTabable( false );
- }
- TabButton* TabControl::AddPage( const UnicodeString& strText, Controls::Base* pPage )
- {
- if ( !pPage )
- {
- pPage = new Base( this );
- }
- else
- {
- pPage->SetParent( this );
- }
- TabButton* pButton = new TabButton( m_TabStrip );
- pButton->SetText( strText );
- pButton->SetPage( pPage );
- pButton->SetTabable( false );
- AddPage( pButton );
- return pButton;
- }
- void TabControl::AddPage( TabButton* pButton )
- {
- Base* pPage = pButton->GetPage();
- pPage->SetParent( this );
- pPage->SetHidden( true );
- pPage->SetMargin( Margin( 6, 6, 6, 6 ) );
- pPage->Dock( Pos::Fill );
- pButton->SetParent( m_TabStrip );
- pButton->Dock( Pos::Left );
- pButton->SizeToContents();
- if ( pButton->GetTabControl() ) pButton->onPress.RemoveHandler( pButton->GetTabControl() );
- pButton->SetTabControl( this );
- pButton->onPress.Add( this, &TabControl::OnTabPressed );
- if ( !m_pCurrentButton )
- {
- pButton->OnPress();
- }
- onAddTab.Call( this );
- Invalidate();
- }
- void TabControl::OnTabPressed( Controls::Base* control )
- {
- if (!control)
- return;
- TabButton* pButton = control->DynamicCastTabButton();
- if ( !pButton ) return;
- Base* pPage = pButton->GetPage();
- if ( !pPage ) return;
- if ( m_pCurrentButton == pButton)
- return;
- if ( m_pCurrentButton )
- {
- Base* pPage = m_pCurrentButton->GetPage();
- if ( pPage )
- {
- pPage->SetHidden( true );
- }
- m_pCurrentButton = NULL;
- }
- m_pCurrentButton = pButton;
- pPage->SetHidden( false );
-
- m_TabStrip->Invalidate();
- Invalidate();
- }
- void TabControl::PostLayout( Skin::Base* skin )
- {
- BaseClass::PostLayout( skin );
- HandleOverflow();
- if ( m_TabStrip->Hidden() )
- {
- m_InnerPanel->DynamicCastTabControlInner()->UpdateCurrentButton( Gwen::Rect( 0, 0, 0, 0 ) );
- }
- else if ( m_pCurrentButton )
- {
- Gwen::Rect rct;
- Gwen::Point p = m_pCurrentButton->LocalPosToCanvas( Gwen::Point( 0, 0 ) );
- p = m_InnerPanel->CanvasPosToLocal( p );
- rct = Gwen::Rect( p.x+1, p.y+1, m_pCurrentButton->Width()-2, m_pCurrentButton->Height()-2 );
- m_InnerPanel->DynamicCastTabControlInner()->UpdateCurrentButton( rct );
- }
-
- }
- void TabControl::OnLoseTab( TabButton* pButton )
- {
- if ( m_pCurrentButton == pButton )
- m_pCurrentButton = NULL;
- //TODO: Select a tab if any exist.
- onLoseTab.Call( this );
- Invalidate();
- }
- int TabControl::TabCount( void )
- {
- return m_TabStrip->NumChildren();
- }
- void TabControl::SetTabStripPosition( int iDock )
- {
- m_TabStrip->SetTabPosition( iDock );
- }
- bool TabControl::DoesAllowDrag()
- {
- return m_TabStrip->AllowsTabReorder();
- }
- void TabControl::HandleOverflow()
- {
- Gwen::Point TabsSize = m_TabStrip->ChildrenSize();
- // Only enable the scrollers if the tabs are at the top.
- // This is a limitation we should explore.
- // Really TabControl should have derivitives for tabs placed elsewhere where we could specialize
- // some functions like this for each direction.
- bool bNeeded = TabsSize.x > Width() && m_TabStrip->GetDock() == Pos::Top;
- m_pScroll[0]->SetHidden( !bNeeded );
- m_pScroll[1]->SetHidden( !bNeeded );
- if ( !bNeeded ) return;
- m_iScrollOffset = Gwen::Clamp( m_iScrollOffset, 0, TabsSize.x - Width() + 32 );
- #if 0
- //
- // This isn't frame rate independent.
- // Could be better. Get rid of m_iScrollOffset and just use m_TabStrip->GetMargin().left ?
- // Then get a margin animation type and do it properly!
- // TODO!
- //
- m_TabStrip->SetMargin( Margin( Gwen::Approach( m_TabStrip->GetMargin().left, m_iScrollOffset * -1, 2 ), 0, 0, 0 ) );
- InvalidateParent();
- #else
- m_TabStrip->SetMargin( Margin( m_iScrollOffset * -1, 0, 0, 0 ) );
- #endif
- m_pScroll[0]->SetPos( Width() - 30 , 5 );
- m_pScroll[1]->SetPos( m_pScroll[0]->Right(), 5 );
- }
- void TabControl::ScrollPressLeft( Base* pFrom )
- {
- m_iScrollOffset -= 120;
- }
- void TabControl::ScrollPressRight( Base* pFrom )
- {
- m_iScrollOffset += 120;
- }
|