mirror of
https://github.com/bulletphysics/bullet3
synced 2025-01-18 21:10:05 +00:00
249 lines
5.2 KiB
C++
249 lines
5.2 KiB
C++
/*
|
|
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;
|
|
} |