Files
bullet3/examples/ThirdPartyLibs/Gwen/Controls/Base.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

1115 lines
22 KiB
C++

/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Gwen.h"
#include "Gwen/BaseRender.h"
#include "Gwen/Skin.h"
#include "Gwen/Platform.h"
#include "Gwen/DragAndDrop.h"
#include "Gwen/ToolTip.h"
#include "Gwen/Utility.h"
#include <list>
#ifndef GWEN_NO_ANIMATION
#include "Gwen/Anim.h"
#endif
using namespace Gwen;
using namespace Controls;
Base::Base(Base* pParent)
{
m_Parent = NULL;
m_ActualParent = NULL;
m_InnerPanel = NULL;
m_Skin = NULL;
SetParent(pParent);
m_bHidden = false;
m_Bounds = Gwen::Rect(0, 0, 10, 10);
m_Padding = Padding(0, 0, 0, 0);
m_Margin = Margin(0, 0, 0, 0);
m_iDock = 0;
m_DragAndDrop_Package = NULL;
m_pUserData = NULL;
RestrictToParent(false);
SetMouseInputEnabled(true);
SetKeyboardInputEnabled(false);
Invalidate();
SetCursor(Gwen::CursorType::Normal);
SetToolTip(NULL);
SetTabable(false);
SetShouldDrawBackground(true);
m_bDisabled = false;
m_bCacheTextureDirty = true;
m_bCacheToTexture = false;
}
Base::~Base()
{
{
Canvas* canvas = GetCanvas();
if (canvas)
canvas->PreDelete(this);
}
Base::List::iterator iter = Children.begin();
while (iter != Children.end())
{
Base* pChild = *iter;
iter = Children.erase(iter);
delete pChild;
}
for (AccelMap::iterator accelIt = m_Accelerators.begin(); accelIt != m_Accelerators.end(); ++accelIt)
{
delete accelIt->second;
}
m_Accelerators.clear();
SetParent(NULL);
if (Gwen::HoveredControl == this)
Gwen::HoveredControl = NULL;
if (Gwen::KeyboardFocus == this)
Gwen::KeyboardFocus = NULL;
if (Gwen::MouseFocus == this) Gwen::MouseFocus = NULL;
DragAndDrop::ControlDeleted(this);
ToolTip::ControlDeleted(this);
#ifndef GWEN_NO_ANIMATION
Anim::Cancel(this);
#endif
if (m_DragAndDrop_Package)
{
delete m_DragAndDrop_Package;
m_DragAndDrop_Package = NULL;
}
}
extern int avoidUpdate;
void Base::Invalidate()
{
m_bNeedsLayout = true;
m_bCacheTextureDirty = true;
avoidUpdate = -3;
}
void Base::DelayedDelete()
{
Canvas* canvas = GetCanvas();
canvas->AddDelayedDelete(this);
}
Canvas* Base::GetCanvas()
{
Base* pCanvas = m_Parent;
if (!pCanvas) return NULL;
return pCanvas->GetCanvas();
}
void Base::SetParent(Base* pParent)
{
if (m_Parent == pParent) return;
if (m_Parent)
{
m_Parent->RemoveChild(this);
}
m_Parent = pParent;
m_ActualParent = NULL;
if (m_Parent)
{
m_Parent->AddChild(this);
}
}
void Base::Dock(int iDock)
{
if (m_iDock == iDock) return;
m_iDock = iDock;
Invalidate();
InvalidateParent();
}
int Base::GetDock()
{
return m_iDock;
}
bool Base::Hidden() const
{
return m_bHidden;
}
bool Base::Visible() const
{
if (Hidden()) return false;
if (GetParent())
{
return GetParent()->Visible();
}
return true;
}
void Base::InvalidateChildren(bool bRecursive)
{
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
(*it)->Invalidate();
if (bRecursive)
(*it)->InvalidateChildren(bRecursive);
}
if (m_InnerPanel)
{
for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
{
(*it)->Invalidate();
if (bRecursive)
(*it)->InvalidateChildren(bRecursive);
}
}
}
void Base::Position(int pos, int xpadding, int ypadding)
{
int w = GetParent()->Width();
int h = GetParent()->Height();
const Padding& padding = GetParent()->GetPadding();
int x = X();
int y = Y();
if (pos & Pos::Left) x = padding.left + xpadding;
if (pos & Pos::Right) x = w - Width() - padding.right - xpadding;
if (pos & Pos::CenterH) x = padding.left + xpadding + (w - Width() - padding.left - padding.right) * 0.5;
if (pos & Pos::Top) y = padding.top + ypadding;
if (pos & Pos::Bottom) y = h - Height() - padding.bottom - ypadding;
if (pos & Pos::CenterV) y = padding.top + ypadding + (h - Height() - padding.bottom - padding.top) * 0.5;
SetPos(x, y);
}
void Base::SendToBack()
{
if (!m_Parent) return;
if (m_Parent->Children.front() == this) return;
m_Parent->Children.remove(this);
m_Parent->Children.push_front(this);
InvalidateParent();
}
void Base::BringToFront()
{
if (!m_Parent) return;
if (m_Parent->Children.back() == this) return;
m_Parent->Children.remove(this);
m_Parent->Children.push_back(this);
InvalidateParent();
}
Controls::Base* Base::FindChildByName(const Gwen::String& name, bool bRecursive)
{
Base::List::iterator iter;
for (iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
if (pChild->GetName() == name)
return pChild;
if (bRecursive)
{
Controls::Base* pSubChild = pChild->FindChildByName(name, true);
if (pSubChild)
return pSubChild;
}
}
return NULL;
}
void Base::BringNextToControl(Controls::Base* pChild, bool bBehind)
{
if (!m_Parent) return;
m_Parent->Children.remove(this);
Base::List::iterator it = std::find(m_Parent->Children.begin(), m_Parent->Children.end(), pChild);
if (it == m_Parent->Children.end())
return BringToFront();
if (bBehind)
{
++it;
if (it == m_Parent->Children.end())
return BringToFront();
}
m_Parent->Children.insert(it, this);
InvalidateParent();
}
void Base::AddChild(Base* pChild)
{
if (m_InnerPanel)
{
m_InnerPanel->AddChild(pChild);
return;
}
Children.push_back(pChild);
OnChildAdded(pChild);
pChild->m_ActualParent = this;
}
void Base::RemoveChild(Base* pChild)
{
// If we removed our innerpanel
// remove our pointer to it
if (m_InnerPanel == pChild)
{
m_InnerPanel = NULL;
}
if (m_InnerPanel)
{
m_InnerPanel->RemoveChild(pChild);
}
Children.remove(pChild);
OnChildRemoved(pChild);
}
void Base::RemoveAllChildren()
{
while (Children.size() > 0)
{
RemoveChild(*Children.begin());
}
}
int Base::NumChildren()
{
// Include m_InnerPanel's children here?
return Children.size();
}
void Base::OnChildAdded(Base* /*pChild*/)
{
Invalidate();
}
void Base::OnChildRemoved(Base* /*pChild*/)
{
Invalidate();
}
Skin::Base* Base::GetSkin(void)
{
if (m_Skin) return m_Skin;
if (m_Parent) return m_Parent->GetSkin();
Debug::AssertCheck(0, "Base::GetSkin Returning NULL!\n");
return NULL;
}
void Base::MoveBy(int x, int y)
{
SetBounds(X() + x, Y() + y, Width(), Height());
}
void Base::MoveTo(int x, int y)
{
if (m_bRestrictToParent && GetParent())
{
Base* pParent = GetParent();
if (x - GetPadding().left < pParent->GetMargin().left) x = pParent->GetMargin().left + GetPadding().left;
if (y - GetPadding().top < pParent->GetMargin().top) y = pParent->GetMargin().top + GetPadding().top;
if (x + Width() + GetPadding().right > pParent->Width() - pParent->GetMargin().right) x = pParent->Width() - pParent->GetMargin().right - Width() - GetPadding().right;
if (y + Height() + GetPadding().bottom > pParent->Height() - pParent->GetMargin().bottom) y = pParent->Height() - pParent->GetMargin().bottom - Height() - GetPadding().bottom;
}
SetBounds(x, y, Width(), Height());
}
void Base::SetPos(int x, int y)
{
SetBounds(x, y, Width(), Height());
}
bool Base::SetSize(int w, int h)
{
return SetBounds(X(), Y(), w, h);
}
bool Base::SetBounds(const Gwen::Rect& bounds)
{
return SetBounds(bounds.x, bounds.y, bounds.w, bounds.h);
}
bool Base::SetBounds(int x, int y, int w, int h)
{
if (m_Bounds.x == x &&
m_Bounds.y == y &&
m_Bounds.w == w &&
m_Bounds.h == h)
return false;
Gwen::Rect oldBounds = GetBounds();
m_Bounds.x = x;
m_Bounds.y = y;
m_Bounds.w = w;
m_Bounds.h = h;
OnBoundsChanged(oldBounds);
return true;
}
void Base::OnBoundsChanged(Gwen::Rect oldBounds)
{
//Anything that needs to update on size changes
//Iterate my children and tell them I've changed
//
if (m_Bounds.w != oldBounds.w || m_Bounds.h != oldBounds.h)
{
if (GetParent())
GetParent()->OnChildBoundsChanged(oldBounds, this);
Invalidate();
}
Redraw();
UpdateRenderBounds();
}
void Base::OnScaleChanged()
{
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
(*iter)->OnScaleChanged();
}
}
void Base::OnChildBoundsChanged(Gwen::Rect /*oldChildBounds*/, Base* /*pChild*/)
{
}
void Base::Render(Gwen::Skin::Base* /*skin*/)
{
}
void Base::DoCacheRender(Gwen::Skin::Base* skin, Gwen::Controls::Base* pMaster)
{
Gwen::Renderer::Base* render = skin->GetRender();
Gwen::Renderer::ICacheToTexture* cache = render->GetCTT();
if (!cache) return;
Gwen::Point pOldRenderOffset = render->GetRenderOffset();
Gwen::Rect rOldRegion = render->ClipRegion();
if (this != pMaster)
{
render->AddRenderOffset(GetBounds());
render->AddClipRegion(GetBounds());
}
else
{
render->SetRenderOffset(Gwen::Point(0, 0));
render->SetClipRegion(GetBounds());
}
if (m_bCacheTextureDirty && render->ClipRegionVisible())
{
render->StartClip();
if (ShouldCacheToTexture())
cache->SetupCacheTexture(this);
//Render myself first
Render(skin);
if (!Children.empty())
{
//Now render my kids
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
if (pChild->Hidden()) continue;
pChild->DoCacheRender(skin, pMaster);
}
}
if (ShouldCacheToTexture())
{
cache->FinishCacheTexture(this);
m_bCacheTextureDirty = false;
}
}
render->SetClipRegion(rOldRegion);
render->StartClip();
render->SetRenderOffset(pOldRenderOffset);
cache->DrawCachedControlTexture(this);
}
void Base::DoRender(Gwen::Skin::Base* skin)
{
// If this control has a different skin,
// then so does its children.
if (m_Skin)
skin = m_Skin;
// Do think
Think();
Gwen::Renderer::Base* render = skin->GetRender();
if (render->GetCTT() && ShouldCacheToTexture())
{
DoCacheRender(skin, this);
return;
}
Gwen::Point pOldRenderOffset = render->GetRenderOffset();
render->AddRenderOffset(GetBounds());
RenderUnder(skin);
Gwen::Rect rOldRegion = render->ClipRegion();
render->AddClipRegion(GetBounds());
if (render->ClipRegionVisible())
{
render->StartClip();
//Render myself first
Render(skin);
if (!Children.empty())
{
//Now render my kids
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
if (pChild->Hidden()) continue;
pChild->DoRender(skin);
}
}
render->SetClipRegion(rOldRegion);
render->StartClip();
RenderOver(skin);
}
else
{
render->SetClipRegion(rOldRegion);
}
RenderFocus(skin);
render->SetRenderOffset(pOldRenderOffset);
}
void Base::SetSkin(Skin::Base* skin, bool doChildren)
{
if (m_Skin == skin) return;
m_Skin = skin;
Invalidate();
Redraw();
OnSkinChanged(skin);
if (doChildren)
{
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
(*it)->SetSkin(skin, true);
}
}
}
void Base::OnSkinChanged(Skin::Base* /*skin*/)
{
//Do something
}
bool Base::OnMouseWheeled(int iDelta)
{
if (m_ActualParent)
return m_ActualParent->OnMouseWheeled(iDelta);
return false;
}
void Base::OnMouseMoved(int /*x*/, int /*y*/, int /*deltaX*/, int /*deltaY*/)
{
}
void Base::OnMouseEnter()
{
onHoverEnter.Call(this);
if (GetToolTip())
ToolTip::Enable(this);
else if (GetParent() && GetParent()->GetToolTip())
ToolTip::Enable(GetParent());
}
void Base::OnMouseLeave()
{
onHoverLeave.Call(this);
if (GetToolTip())
ToolTip::Disable(this);
}
bool Base::IsHovered()
{
return Gwen::HoveredControl == this;
}
bool Base::ShouldDrawHover()
{
return Gwen::MouseFocus == this || Gwen::MouseFocus == NULL;
}
bool Base::HasFocus()
{
return Gwen::KeyboardFocus == this;
}
void Base::Focus()
{
if (Gwen::KeyboardFocus == this) return;
if (Gwen::KeyboardFocus)
Gwen::KeyboardFocus->OnLostKeyboardFocus();
Gwen::KeyboardFocus = this;
OnKeyboardFocus();
Redraw();
}
void Base::Blur()
{
if (Gwen::KeyboardFocus != this) return;
Gwen::KeyboardFocus = NULL;
OnLostKeyboardFocus();
Redraw();
}
bool Base::IsOnTop()
{
Base::List::iterator iter = GetParent()->Children.begin();
Base* pChild = *iter;
if (pChild == this)
return true;
return false;
}
void Base::Touch()
{
if (GetParent())
GetParent()->OnChildTouched(this);
}
void Base::OnChildTouched(Controls::Base* /*pChild*/)
{
Touch();
}
Base* Base::GetControlAt(int x, int y)
{
if (Hidden())
return NULL;
if (x < 0 || y < 0 || x >= Width() || y >= Height())
return NULL;
Base::List::reverse_iterator iter;
for (iter = Children.rbegin(); iter != Children.rend(); ++iter)
{
Base* pChild = *iter;
Base* pFound = NULL;
pFound = pChild->GetControlAt(x - pChild->X(), y - pChild->Y());
if (pFound) return pFound;
}
if (!GetMouseInputEnabled())
return NULL;
return this;
}
void Base::Layout(Skin::Base* skin)
{
if (skin->GetRender()->GetCTT() && ShouldCacheToTexture())
skin->GetRender()->GetCTT()->CreateControlCacheTexture(this);
}
int avoidUpdate = -15;
void Base::RecurseLayout(Skin::Base* skin)
{
if (m_Skin) skin = m_Skin;
if (Hidden()) return;
if (NeedsLayout())
{
m_bNeedsLayout = false;
Layout(skin);
}
if (avoidUpdate > 0)
return;
Gwen::Rect rBounds = GetRenderBounds();
// Adjust bounds for padding
rBounds.x += m_Padding.left;
rBounds.w -= m_Padding.left + m_Padding.right;
rBounds.y += m_Padding.top;
rBounds.h -= m_Padding.top + m_Padding.bottom;
int sz = Children.size();
if (sz > 100)
{
// printf("!\n");
}
int curChild = 0;
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
curChild++;
if (pChild->Hidden())
continue;
int iDock = pChild->GetDock();
if (iDock & Pos::Fill)
continue;
if (iDock & Pos::Top)
{
const Margin& margin = pChild->GetMargin();
pChild->SetBounds(rBounds.x + margin.left, rBounds.y + margin.top, rBounds.w - margin.left - margin.right, pChild->Height());
int iHeight = margin.top + margin.bottom + pChild->Height();
rBounds.y += iHeight;
rBounds.h -= iHeight;
}
if (iDock & Pos::Left)
{
const Margin& margin = pChild->GetMargin();
pChild->SetBounds(rBounds.x + margin.left, rBounds.y + margin.top, pChild->Width(), rBounds.h - margin.top - margin.bottom);
int iWidth = margin.left + margin.right + pChild->Width();
rBounds.x += iWidth;
rBounds.w -= iWidth;
}
if (iDock & Pos::Right)
{
// TODO: THIS MARGIN CODE MIGHT NOT BE FULLY FUNCTIONAL
const Margin& margin = pChild->GetMargin();
pChild->SetBounds((rBounds.x + rBounds.w) - pChild->Width() - margin.right, rBounds.y + margin.top, pChild->Width(), rBounds.h - margin.top - margin.bottom);
int iWidth = margin.left + margin.right + pChild->Width();
rBounds.w -= iWidth;
}
if (iDock & Pos::Bottom)
{
// TODO: THIS MARGIN CODE MIGHT NOT BE FULLY FUNCTIONAL
const Margin& margin = pChild->GetMargin();
pChild->SetBounds(rBounds.x + margin.left, (rBounds.y + rBounds.h) - pChild->Height() - margin.bottom, rBounds.w - margin.left - margin.right, pChild->Height());
rBounds.h -= pChild->Height() + margin.bottom + margin.top;
}
pChild->RecurseLayout(skin);
}
m_InnerBounds = rBounds;
curChild = 0;
//
// Fill uses the left over space, so do that now.
//
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
int iDock = pChild->GetDock();
curChild++;
if (!(iDock & Pos::Fill))
continue;
const Margin& margin = pChild->GetMargin();
pChild->SetBounds(rBounds.x + margin.left, rBounds.y + margin.top, rBounds.w - margin.left - margin.right, rBounds.h - margin.top - margin.bottom);
pChild->RecurseLayout(skin);
}
PostLayout(skin);
if (IsTabable())
{
if (!GetCanvas()->FirstTab) GetCanvas()->FirstTab = this;
if (!GetCanvas()->NextTab) GetCanvas()->NextTab = this;
}
if (Gwen::KeyboardFocus == this)
{
GetCanvas()->NextTab = NULL;
}
}
bool Base::IsChild(Controls::Base* pChild)
{
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
if (pChild == (*iter)) return true;
}
return false;
}
Gwen::Point Base::LocalPosToCanvas(const Gwen::Point& pnt)
{
if (m_Parent)
{
int x = pnt.x + X();
int y = pnt.y + Y();
// If our parent has an innerpanel and we're a child of it
// add its offset onto us.
//
if (m_Parent->m_InnerPanel && m_Parent->m_InnerPanel->IsChild(this))
{
x += m_Parent->m_InnerPanel->X();
y += m_Parent->m_InnerPanel->Y();
}
return m_Parent->LocalPosToCanvas(Gwen::Point(x, y));
}
return pnt;
}
Gwen::Point Base::CanvasPosToLocal(const Gwen::Point& pnt)
{
if (m_Parent)
{
int x = pnt.x - X();
int y = pnt.y - Y();
// If our parent has an innerpanel and we're a child of it
// add its offset onto us.
//
if (m_Parent->m_InnerPanel && m_Parent->m_InnerPanel->IsChild(this))
{
x -= m_Parent->m_InnerPanel->X();
y -= m_Parent->m_InnerPanel->Y();
}
return m_Parent->CanvasPosToLocal(Gwen::Point(x, y));
}
return pnt;
}
bool Base::IsMenuComponent()
{
if (!m_Parent) return false;
return m_Parent->IsMenuComponent();
}
void Base::CloseMenus()
{
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
(*it)->CloseMenus();
}
}
void Base::UpdateRenderBounds()
{
m_RenderBounds.x = 0;
m_RenderBounds.x = 0;
m_RenderBounds.w = m_Bounds.w;
m_RenderBounds.h = m_Bounds.h;
}
void Base::UpdateCursor()
{
Platform::SetCursor(m_Cursor);
}
DragAndDrop::Package* Base::DragAndDrop_GetPackage(int /*x*/, int /*y*/)
{
return m_DragAndDrop_Package;
}
bool Base::DragAndDrop_HandleDrop(Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/)
{
DragAndDrop::SourceControl->SetParent(this);
return true;
}
bool Base::DragAndDrop_Draggable()
{
if (!m_DragAndDrop_Package) return false;
return m_DragAndDrop_Package->draggable;
}
void Base::DragAndDrop_SetPackage(bool bDraggable, const String& strName, void* pUserData)
{
if (!m_DragAndDrop_Package)
{
m_DragAndDrop_Package = new Gwen::DragAndDrop::Package();
}
m_DragAndDrop_Package->draggable = bDraggable;
m_DragAndDrop_Package->name = strName;
m_DragAndDrop_Package->userdata = pUserData;
}
void Base::DragAndDrop_StartDragging(Gwen::DragAndDrop::Package* pPackage, int x, int y)
{
pPackage->holdoffset = CanvasPosToLocal(Gwen::Point(x, y));
pPackage->drawcontrol = this;
}
bool Base::SizeToChildren(bool w, bool h)
{
Gwen::Point size = ChildrenSize();
return SetSize(w ? size.x : Width(), h ? size.y : Height());
}
Gwen::Point Base::ChildrenSize()
{
Gwen::Point size;
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
if (pChild->Hidden()) continue;
size.x = GwenUtil_Max(size.x, pChild->Right());
size.y = GwenUtil_Max(size.y, pChild->Bottom());
}
return size;
}
void Base::SetPadding(const Padding& padding)
{
if (m_Padding.left == padding.left &&
m_Padding.top == padding.top &&
m_Padding.right == padding.right &&
m_Padding.bottom == padding.bottom)
return;
m_Padding = padding;
Invalidate();
InvalidateParent();
}
void Base::SetMargin(const Margin& margin)
{
if (m_Margin.top == margin.top &&
m_Margin.left == margin.left &&
m_Margin.bottom == margin.bottom &&
m_Margin.right == margin.right)
return;
m_Margin = margin;
Invalidate();
InvalidateParent();
}
bool Base::HandleAccelerator(Gwen::UnicodeString& accelerator)
{
if (Gwen::KeyboardFocus == this || !AccelOnlyFocus())
{
AccelMap::iterator iter = m_Accelerators.find(accelerator);
if (iter != m_Accelerators.end())
{
iter->second->Call(this);
return true;
}
}
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
if ((*it)->HandleAccelerator(accelerator))
return true;
}
return false;
}
bool Base::OnKeyPress(int iKey, bool bPress)
{
bool bHandled = false;
switch (iKey)
{
case Key::Tab:
bHandled = OnKeyTab(bPress);
break;
case Key::Space:
bHandled = OnKeySpace(bPress);
break;
case Key::Home:
bHandled = OnKeyHome(bPress);
break;
case Key::End:
bHandled = OnKeyEnd(bPress);
break;
case Key::Return:
bHandled = OnKeyReturn(bPress);
break;
case Key::Backspace:
bHandled = OnKeyBackspace(bPress);
break;
case Key::Delete:
bHandled = OnKeyDelete(bPress);
break;
case Key::Right:
bHandled = OnKeyRight(bPress);
break;
case Key::Left:
bHandled = OnKeyLeft(bPress);
break;
case Key::Up:
bHandled = OnKeyUp(bPress);
break;
case Key::Down:
bHandled = OnKeyDown(bPress);
break;
case Key::Escape:
bHandled = OnKeyEscape(bPress);
break;
default:
break;
}
if (!bHandled && GetParent())
GetParent()->OnKeyPress(iKey, bPress);
return bHandled;
}
bool Base::OnKeyRelease(int iKey)
{
return OnKeyPress(iKey, false);
}
bool Base::OnKeyTab(bool bDown)
{
if (!bDown) return true;
if (GetCanvas()->NextTab)
{
GetCanvas()->NextTab->Focus();
Redraw();
}
return true;
}
void Base::RenderFocus(Gwen::Skin::Base* skin)
{
if (Gwen::KeyboardFocus != this) return;
if (!IsTabable()) return;
skin->DrawKeyboardHighlight(this, GetRenderBounds(), 3);
}
void Base::SetToolTip(const String& strText)
{
SetToolTip(Gwen::Utility::StringToUnicode(strText));
}
void Base::SetToolTip(const UnicodeString& strText)
{
Label* tooltip = new Label(this);
tooltip->SetText(strText);
tooltip->SizeToContents();
SetToolTip(tooltip);
}
#ifndef GWEN_NO_ANIMATION
void Base::Anim_WidthIn(float fLength, float fDelay, float fEase)
{
Gwen::Anim::Add(this, new Gwen::Anim::Size::Width(0, Width(), fLength, false, fDelay, fEase));
SetWidth(0);
}
void Base::Anim_HeightIn(float fLength, float fDelay, float fEase)
{
Gwen::Anim::Add(this, new Gwen::Anim::Size::Height(0, Height(), fLength, false, fDelay, fEase));
SetHeight(0);
}
void Base::Anim_WidthOut(float fLength, bool bHide, float fDelay, float fEase)
{
Gwen::Anim::Add(this, new Gwen::Anim::Size::Width(Width(), 0, fLength, bHide, fDelay, fEase));
}
void Base::Anim_HeightOut(float fLength, bool bHide, float fDelay, float fEase)
{
Gwen::Anim::Add(this, new Gwen::Anim::Size::Height(Height(), 0, fLength, bHide, fDelay, fEase));
}
#endif