bullet3/examples/ThirdPartyLibs/Gwen/Controls/DockBase.cpp

343 lines
7.6 KiB
C++

/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/DockBase.h"
#include "Gwen/Controls/DockedTabControl.h"
#include "Gwen/Controls/Highlight.h"
#include "Gwen/DragAndDrop.h"
#include "Gwen/Controls/Resizer.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR( DockBase )
{
SetPadding( Padding( 1, 1, 1, 1 ) );
SetSize( 200, 200 );
m_DockedTabControl = NULL;
m_Left = NULL;
m_Right = NULL;
m_Top = NULL;
m_Bottom = NULL;
m_bDrawHover = false;
}
TabControl* DockBase::GetTabControl()
{
return m_DockedTabControl;
}
void DockBase::SetupChildDock( int iPos )
{
if ( !m_DockedTabControl )
{
m_DockedTabControl = new DockedTabControl( this );
m_DockedTabControl->onLoseTab.Add( this, &DockBase::OnTabRemoved );
m_DockedTabControl->SetTabStripPosition( Pos::Bottom );
m_DockedTabControl->SetShowTitlebar( true );
}
Dock( iPos );
int iSizeDirection = Pos::Left;
if ( iPos == Pos::Left ) iSizeDirection = Pos::Right;
if ( iPos == Pos::Top ) iSizeDirection = Pos::Bottom;
if ( iPos == Pos::Bottom ) iSizeDirection = Pos::Top;
ControlsInternal::Resizer* sizer = new ControlsInternal::Resizer( this );
sizer->Dock( iSizeDirection );
sizer->SetResizeDir( iSizeDirection );
sizer->SetSize( 2, 2 );
sizer->SetTarget( this );
}
void DockBase::Render( Skin::Base* /*skin*/ )
{
//Gwen::Render->SetDrawColor( Colors::Black );
//Gwen::Render->DrawLinedRect( GetRenderBounds() );
}
DockBase** DockBase::GetChildDockPtr( int iPos )
{
if ( iPos == Pos::Left ) return &m_Left;
if ( iPos == Pos::Right ) return &m_Right;
if ( iPos == Pos::Top ) return &m_Top;
if ( iPos == Pos::Bottom ) return &m_Bottom;
return NULL;
}
DockBase* DockBase::GetChildDock( int iPos )
{
DockBase** pDock = GetChildDockPtr( iPos );
if ( !(*pDock) )
{
(*pDock) = new DockBase( this );
(*pDock)->SetupChildDock( iPos );
}
else
{
(*pDock)->SetHidden( false );
}
return *pDock;
}
int DockBase::GetDroppedTabDirection( int x, int y )
{
int w = Width();
int h = Height();
float top = (float)y / (float) h;
float left = (float)x / (float) w;
float right = (float)(w - x) /(float) w;
float bottom = (float)(h - y) / (float) h;
float minimum = GwenUtil_Min( GwenUtil_Min( GwenUtil_Min( top, left ), right ), bottom );
m_bDropFar = ( minimum < 0.2f );
if ( minimum > 0.3 ) return Pos::Fill;
if ( top == minimum && (!m_Top || m_Top->Hidden()) ) return Pos::Top;
if ( left == minimum && (!m_Left || m_Left->Hidden()) ) return Pos::Left;
if ( right == minimum && (!m_Right || m_Right->Hidden()) ) return Pos::Right;
if ( bottom == minimum && (!m_Bottom || m_Bottom->Hidden()) ) return Pos::Bottom;
return Pos::Fill;
}
bool DockBase::DragAndDrop_CanAcceptPackage( Gwen::DragAndDrop::Package* pPackage )
{
// A TAB button dropped
if ( pPackage->name == "TabButtonMove" )
return true;
// a TAB window dropped
if ( pPackage->name == "TabWindowMove" )
return true;
return false;
}
void AddTabToDock( TabButton* pTabButton, DockedTabControl* pControl )
{
pControl->AddPage( pTabButton );
}
bool DockBase::DragAndDrop_HandleDrop( Gwen::DragAndDrop::Package* pPackage, int x, int y )
{
Gwen::Point pPos = CanvasPosToLocal( Gwen::Point( x, y ) );
int dir = GetDroppedTabDirection( pPos.x, pPos.y );
DockedTabControl* pAddTo = m_DockedTabControl;
if ( dir == Pos::Fill && pAddTo == NULL ) return false;
if ( dir != Pos::Fill )
{
DockBase* pDock = GetChildDock( dir );
pAddTo = pDock->m_DockedTabControl;
if ( !m_bDropFar ) pDock->BringToFront();
else pDock->SendToBack();
}
if ( pPackage->name == "TabButtonMove" )
{
TabButton* pTabButton = DragAndDrop::SourceControl->DynamicCastTabButton();
if ( !pTabButton ) return false;
AddTabToDock( pTabButton, pAddTo );
}
if ( pPackage->name == "TabWindowMove" )
{
DockedTabControl* pTabControl = DragAndDrop::SourceControl->DynamicCastDockedTabControl();
if ( !pTabControl ) return false;
if ( pTabControl == pAddTo ) return false;
pTabControl->MoveTabsTo( pAddTo );
}
Invalidate();
return true;
}
bool DockBase::IsEmpty()
{
if ( m_DockedTabControl && m_DockedTabControl->TabCount() > 0 ) return false;
if ( m_Left && !m_Left->IsEmpty() ) return false;
if ( m_Right && !m_Right->IsEmpty() ) return false;
if ( m_Top && !m_Top->IsEmpty() ) return false;
if ( m_Bottom && !m_Bottom->IsEmpty() ) return false;
return true;
}
void DockBase::OnTabRemoved( Gwen::Controls::Base* /*pControl*/ )
{
DoRedundancyCheck();
DoConsolidateCheck();
}
void DockBase::DoRedundancyCheck()
{
if ( !IsEmpty() ) return;
DockBase* pDockParent = GetParent()->DynamicCastDockBase();
if ( !pDockParent ) return;
pDockParent->OnRedundantChildDock( this );
}
void DockBase::DoConsolidateCheck()
{
if ( IsEmpty() ) return;
if ( !m_DockedTabControl ) return;
if ( m_DockedTabControl->TabCount() > 0 ) return;
if ( m_Bottom && !m_Bottom->IsEmpty() )
{
m_Bottom->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
return;
}
if ( m_Top && !m_Top->IsEmpty() )
{
m_Top->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
return;
}
if ( m_Left && !m_Left->IsEmpty() )
{
m_Left->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
return;
}
if ( m_Right && !m_Right->IsEmpty() )
{
m_Right->m_DockedTabControl->MoveTabsTo( m_DockedTabControl );
return;
}
}
void DockBase::OnRedundantChildDock( DockBase* pDockBase )
{
pDockBase->SetHidden( true );
DoRedundancyCheck();
DoConsolidateCheck();
}
void DockBase::DragAndDrop_HoverEnter( Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/ )
{
m_bDrawHover = true;
}
void DockBase::DragAndDrop_HoverLeave( Gwen::DragAndDrop::Package* /*pPackage*/ )
{
m_bDrawHover = false;
}
void DockBase::DragAndDrop_Hover( Gwen::DragAndDrop::Package* /*pPackage*/, int x, int y )
{
Gwen::Point pPos = CanvasPosToLocal( Gwen::Point( x, y ) );
int dir = GetDroppedTabDirection( pPos.x, pPos.y );
if ( dir == Pos::Fill )
{
if ( !m_DockedTabControl )
{
m_HoverRect = Gwen::Rect( 0, 0, 0, 0 );
return;
}
m_HoverRect = GetInnerBounds();
return;
}
m_HoverRect = GetRenderBounds();
int HelpBarWidth = 0;
if ( dir == Pos::Left )
{
HelpBarWidth = m_HoverRect.w * 0.25f;
m_HoverRect.w = HelpBarWidth;
}
if ( dir == Pos::Right )
{
HelpBarWidth = m_HoverRect.w * 0.25f;
m_HoverRect.x = m_HoverRect.w - HelpBarWidth;
m_HoverRect.w = HelpBarWidth;
}
if ( dir == Pos::Top )
{
HelpBarWidth = m_HoverRect.h * 0.25f;
m_HoverRect.h = HelpBarWidth;
}
if ( dir == Pos::Bottom )
{
HelpBarWidth = m_HoverRect.h * 0.25f;
m_HoverRect.y = m_HoverRect.h - HelpBarWidth;
m_HoverRect.h = HelpBarWidth;
}
if ( (dir == Pos::Top || dir == Pos::Bottom ) && !m_bDropFar )
{
if ( m_Left && m_Left->Visible() )
{
m_HoverRect.x += m_Left->Width();
m_HoverRect.w -= m_Left->Width();
}
if ( m_Right && m_Right->Visible() )
{
m_HoverRect.w -= m_Right->Width();
}
}
if ( (dir == Pos::Left || dir == Pos::Right ) && !m_bDropFar )
{
if ( m_Top && m_Top->Visible() )
{
m_HoverRect.y += m_Top->Height();
m_HoverRect.h -= m_Top->Height();
}
if ( m_Bottom && m_Bottom->Visible() )
{
m_HoverRect.h -= m_Bottom->Height();
}
}
}
void DockBase::RenderOver( Skin::Base* skin )
{
if ( !m_bDrawHover ) return;
Gwen::Renderer::Base* render = skin->GetRender();
render->SetDrawColor( Gwen::Color( 255, 100, 255, 20 ) );
render->DrawFilledRect( GetRenderBounds() );
if ( m_HoverRect.w == 0 ) return;
render->SetDrawColor( Gwen::Color( 255, 100, 255, 100 ) );
render->DrawFilledRect( m_HoverRect );
render->SetDrawColor( Gwen::Color( 255, 100, 255, 200 ) );
render->DrawLinedRect( m_HoverRect );
}