Files
bullet3/examples/ThirdPartyLibs/Gwen/Controls/TabControl.cpp
erwincoumans ab8f16961e Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
2018-09-23 14:17:31 -07:00

241 lines
5.1 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;
};
}; // namespace Controls
}; // namespace Gwen
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;
}