* Adjustment: Update Bullet version to 3.24.

This commit is contained in:
Robert MacGregor 2022-06-27 10:01:08 -04:00
parent 35de012ee7
commit 4a3f31df2a
6148 changed files with 2112532 additions and 56873 deletions

View file

@ -0,0 +1,77 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_ALIGN_H
#define GWEN_ALIGN_H
#include "Gwen/Controls/Base.h"
namespace Gwen
{
namespace Align
{
inline void Center(Controls::Base* ctrl)
{
Controls::Base* parent = ctrl->GetParent();
if (!parent) return;
ctrl->SetPos(parent->GetPadding().left + (((parent->Width() - parent->GetPadding().left - parent->GetPadding().right) - ctrl->Width()) / 2),
(parent->Height() - ctrl->Height()) / 2);
}
inline void AlignLeft(Controls::Base* ctrl)
{
Controls::Base* parent = ctrl->GetParent();
if (!parent) return;
ctrl->SetPos(parent->GetPadding().left, ctrl->Y());
}
inline void CenterHorizontally(Controls::Base* ctrl)
{
Controls::Base* parent = ctrl->GetParent();
if (!parent) return;
ctrl->SetPos(parent->GetPadding().left + (((parent->Width() - parent->GetPadding().left - parent->GetPadding().right) - ctrl->Width()) / 2), ctrl->Y());
}
inline void AlignRight(Controls::Base* ctrl)
{
Controls::Base* parent = ctrl->GetParent();
if (!parent) return;
ctrl->SetPos(parent->Width() - ctrl->Width() - parent->GetPadding().right, ctrl->Y());
}
inline void AlignTop(Controls::Base* ctrl)
{
ctrl->SetPos(ctrl->X(), 0);
}
inline void CenterVertically(Controls::Base* ctrl)
{
Controls::Base* parent = ctrl->GetParent();
if (!parent) return;
ctrl->SetPos(ctrl->X(), (parent->Height() - ctrl->Height()) / 2);
}
inline void AlignBottom(Controls::Base* ctrl)
{
Controls::Base* parent = ctrl->GetParent();
if (!parent) return;
ctrl->SetPos(ctrl->X(), parent->Height() - ctrl->Height());
}
inline void PlaceBelow(Controls::Base* ctrl, Controls::Base* below, int iBorder = 0)
{
ctrl->SetPos(ctrl->X(), below->Bottom() + iBorder);
}
} // namespace Align
} // namespace Gwen
#endif

View file

@ -0,0 +1,140 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Anim.h"
#include <math.h>
#include <cmath>
#include "Gwen/Utility.h"
using namespace Gwen;
#ifndef GWEN_NO_ANIMATION
static Gwen::Anim::Animation::List g_Animations;
static Gwen::Anim::Animation::ChildList g_AnimationsListed;
void Gwen::Anim::Add(Gwen::Controls::Base* control, Animation* animation)
{
animation->m_Control = control;
g_Animations[control].push_back(animation);
}
void Gwen::Anim::Cancel(Gwen::Controls::Base* control)
{
/* cannot use std::list iterator with algoryhtmns based on pointers
struct AnimDeletePredicate
{
AnimDeletePredicate( Gwen::Controls::Base* control )
{
this->control = control;
}
bool operator() ( Gwen::Anim::Animation* anim )
{
return anim->m_Control == control;
}
Gwen::Controls::Base* control;
};
std::remove_if ( g_Animations.begin(), g_Animations.end(), AnimDeletePredicate( control ) );
*/
Gwen::Anim::Animation::List::iterator iAnimations;
if ((iAnimations = g_Animations.find(control)) != g_Animations.end())
{
Gwen::Anim::Animation::ChildList& ChildAnimationsForControl = iAnimations->second;
Gwen::Anim::Animation::ChildList::iterator iAnimationChild = ChildAnimationsForControl.begin();
if (iAnimationChild != ChildAnimationsForControl.end())
{
do
{
delete (*iAnimationChild);
} while (++iAnimationChild != ChildAnimationsForControl.end());
}
g_Animations.erase(iAnimations);
}
}
void Gwen::Anim::Think()
{
Gwen::Anim::Animation::List::iterator it = g_Animations.begin();
if (it != g_Animations.end())
{
Gwen::Anim::Animation::ChildList::iterator itChild;
Gwen::Anim::Animation* anim;
do
{
if ((itChild = it->second.begin()) != it->second.end())
{
do
{
anim = *itChild;
anim->Think();
if (anim->Finished())
{
itChild = it->second.erase(itChild);
delete anim;
}
else
{
++itChild;
}
} while (itChild != it->second.end());
}
} while (++it != g_Animations.end());
}
}
Gwen::Anim::TimedAnimation::TimedAnimation(float fLength, float fDelay, float fEase)
{
m_fStart = Platform::GetTimeInSeconds() + fDelay;
m_fEnd = m_fStart + fLength;
m_fEase = fEase;
m_bStarted = false;
m_bFinished = false;
}
void Gwen::Anim::TimedAnimation::Think()
{
if (m_bFinished) return;
float fCurrent = Platform::GetTimeInSeconds();
float fSecondsIn = fCurrent - m_fStart;
if (fSecondsIn < 0.0f) return;
if (!m_bStarted)
{
m_bStarted = true;
OnStart();
}
float fDelta = fSecondsIn / (m_fEnd - m_fStart);
if (fDelta < 0.0f) fDelta = 0.0f;
if (fDelta > 1.0f) fDelta = 1.0f;
Run(std::pow(fDelta, m_fEase));
if (fDelta == 1.0f) {
m_bFinished = true;
OnFinish();
}
}
bool Gwen::Anim::TimedAnimation::Finished()
{
return m_bFinished;
}
#endif

View file

@ -0,0 +1,129 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_ANIM_H
#define GWEN_ANIM_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Platform.h"
#ifndef GWEN_NO_ANIMATION
namespace Gwen
{
namespace Anim
{
class GWEN_EXPORT Animation
{
public:
typedef std::list<Animation*> ChildList;
typedef std::map<Gwen::Controls::Base*, ChildList> List;
virtual void Think() = 0;
virtual bool Finished() = 0;
virtual ~Animation() {}
Gwen::Controls::Base* m_Control;
};
GWEN_EXPORT void Add(Gwen::Controls::Base* control, Animation* animation);
GWEN_EXPORT void Cancel(Gwen::Controls::Base* control);
GWEN_EXPORT void Think();
//
// Timed animation. Provides a useful base for animations.
//
class GWEN_EXPORT TimedAnimation : public Animation
{
public:
TimedAnimation(float fLength, float fDelay = 0.0f, float fEase = 1.0f);
virtual void Think();
virtual bool Finished();
//
// These are the magic functions you should be overriding
//
virtual void OnStart() {}
virtual void Run(float /*delta*/) {}
virtual void OnFinish() {}
protected:
bool m_bStarted;
bool m_bFinished;
float m_fStart;
float m_fEnd;
float m_fEase;
};
namespace Size
{
class GWEN_EXPORT Height : public TimedAnimation
{
public:
Height(int iStartSize, int iEndSize, float fLength, bool bHide = false, float fDelay = 0.0f, float fEase = 1.0f) : TimedAnimation(fLength, fDelay, fEase)
{
m_iStartSize = iStartSize;
m_iDelta = iEndSize - m_iStartSize;
m_bHide = bHide;
}
virtual void OnStart() { m_Control->SetHeight(m_iStartSize); }
virtual void Run(float delta) { m_Control->SetHeight(m_iStartSize + (((float)m_iDelta) * delta)); }
virtual void OnFinish()
{
m_Control->SetHeight(m_iStartSize + m_iDelta);
m_Control->SetHidden(m_bHide);
}
protected:
int m_iStartSize;
int m_iDelta;
bool m_bHide;
};
class Width : public TimedAnimation
{
public:
Width(int iStartSize, int iEndSize, float fLength, bool bHide = false, float fDelay = 0.0f, float fEase = 1.0f) : TimedAnimation(fLength, fDelay, fEase)
{
m_iStartSize = iStartSize;
m_iDelta = iEndSize - m_iStartSize;
m_bHide = bHide;
}
virtual void OnStart() { m_Control->SetWidth(m_iStartSize); }
virtual void Run(float delta) { m_Control->SetWidth(m_iStartSize + (((float)m_iDelta) * delta)); }
virtual void OnFinish()
{
m_Control->SetWidth(m_iStartSize + m_iDelta);
m_Control->SetHidden(m_bHide);
}
protected:
int m_iStartSize;
int m_iDelta;
bool m_bHide;
};
} // namespace Size
namespace Tools
{
class Remove : public TimedAnimation
{
public:
Remove(float fDelay = 0.0f) : TimedAnimation(0.0f, fDelay) {}
virtual void OnFinish() { m_Control->DelayedDelete(); }
};
} // namespace Tools
} // namespace Anim
} // namespace Gwen
#endif
#endif

View file

@ -0,0 +1,219 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/BaseRender.h"
#include "Gwen/Utility.h"
#include "Gwen/Platform.h"
#include <math.h>
#include <cmath>
namespace Gwen
{
namespace Renderer
{
Base::Base()
{
m_RenderOffset = Gwen::Point(0, 0);
m_fScale = 1.0f;
}
Base::~Base()
{
if (GetCTT())
GetCTT()->ShutDown();
}
void Base::RenderText(Gwen::Font* pFont, Gwen::Point pos, const Gwen::String& text)
{
Gwen::UnicodeString str = Gwen::Utility::StringToUnicode(text);
RenderText(pFont, pos, str);
}
Gwen::Point Base::MeasureText(Gwen::Font* pFont, const Gwen::String& text)
{
Gwen::UnicodeString str = Gwen::Utility::StringToUnicode(text);
return MeasureText(pFont, str);
}
void Base::DrawLinedRect(Gwen::Rect rect)
{
DrawFilledRect(Gwen::Rect(rect.x, rect.y, rect.w, 1));
DrawFilledRect(Gwen::Rect(rect.x, rect.y + rect.h - 1, rect.w, 1));
DrawFilledRect(Gwen::Rect(rect.x, rect.y, 1, rect.h));
DrawFilledRect(Gwen::Rect(rect.x + rect.w - 1, rect.y, 1, rect.h));
};
void Base::DrawPixel(int x, int y)
{
DrawFilledRect(Gwen::Rect(x, y, 1, 1));
}
void Base::DrawShavedCornerRect(Gwen::Rect rect, bool bSlight)
{
// Draw INSIDE the w/h.
rect.w -= 1;
rect.h -= 1;
if (bSlight)
{
DrawFilledRect(Gwen::Rect(rect.x + 1, rect.y, rect.w - 1, 1));
DrawFilledRect(Gwen::Rect(rect.x + 1, rect.y + rect.h, rect.w - 1, 1));
DrawFilledRect(Gwen::Rect(rect.x, rect.y + 1, 1, rect.h - 1));
DrawFilledRect(Gwen::Rect(rect.x + rect.w, rect.y + 1, 1, rect.h - 1));
return;
}
DrawPixel(rect.x + 1, rect.y + 1);
DrawPixel(rect.x + rect.w - 1, rect.y + 1);
DrawPixel(rect.x + 1, rect.y + rect.h - 1);
DrawPixel(rect.x + rect.w - 1, rect.y + rect.h - 1);
DrawFilledRect(Gwen::Rect(rect.x + 2, rect.y, rect.w - 3, 1));
DrawFilledRect(Gwen::Rect(rect.x + 2, rect.y + rect.h, rect.w - 3, 1));
DrawFilledRect(Gwen::Rect(rect.x, rect.y + 2, 1, rect.h - 3));
DrawFilledRect(Gwen::Rect(rect.x + rect.w, rect.y + 2, 1, rect.h - 3));
}
void Base::Translate(int& x, int& y)
{
x += m_RenderOffset.x;
y += m_RenderOffset.y;
x = std::ceil(((float)x) * m_fScale);
y = std::ceil(((float)y) * m_fScale);
}
void Base::Translate(Gwen::Rect& rect)
{
Translate(rect.x, rect.y);
rect.w = std::ceil(((float)rect.w) * m_fScale);
rect.h = std::ceil(((float)rect.h) * m_fScale);
}
void Gwen::Renderer::Base::SetClipRegion(Gwen::Rect rect)
{
m_rectClipRegion = rect;
}
void Base::AddClipRegion(Gwen::Rect rect)
{
rect.x = m_RenderOffset.x;
rect.y = m_RenderOffset.y;
Gwen::Rect out = rect;
if (rect.x < m_rectClipRegion.x)
{
out.w -= (m_rectClipRegion.x - out.x);
out.x = m_rectClipRegion.x;
}
if (rect.y < m_rectClipRegion.y)
{
out.h -= (m_rectClipRegion.y - out.y);
out.y = m_rectClipRegion.y;
}
if (rect.x + rect.w > m_rectClipRegion.x + m_rectClipRegion.w)
{
out.w = (m_rectClipRegion.x + m_rectClipRegion.w) - out.x;
}
if (rect.y + rect.h > m_rectClipRegion.y + m_rectClipRegion.h)
{
out.h = (m_rectClipRegion.y + m_rectClipRegion.h) - out.y;
}
m_rectClipRegion = out;
}
const Gwen::Rect& Base::ClipRegion() const
{
return m_rectClipRegion;
}
bool Base::ClipRegionVisible()
{
if (m_rectClipRegion.w <= 0 || m_rectClipRegion.h <= 0)
return false;
return true;
}
void Base::DrawMissingImage(Gwen::Rect pTargetRect)
{
SetDrawColor(Colors::Red);
DrawFilledRect(pTargetRect);
}
/*
If they haven't defined these font functions in their renderer code
we just draw some rects where the letters would be to give them an idea.
*/
void Base::RenderText(Gwen::Font* pFont, Gwen::Point pos, const Gwen::UnicodeString& text)
{
float fSize = pFont->size * Scale();
for (float i = 0; i < text.length(); i++)
{
wchar_t chr = text[i];
if (chr == ' ') continue;
Gwen::Rect r(pos.x + i * fSize * 0.4, pos.y, fSize * 0.4 - 1, fSize);
/*
This isn't important, it's just me messing around changing the
shape of the rect based on the letter.. just for fun.
*/
if (chr == 'l' || chr == 'i' || chr == '!' || chr == 't')
{
r.w = 1;
}
else if (chr >= 'a' && chr <= 'z')
{
r.y += fSize * 0.5f;
r.h -= fSize * 0.4f;
}
else if (chr == '.' || chr == ',')
{
r.x += 2;
r.y += r.h - 2;
r.w = 2;
r.h = 2;
}
else if (chr == '\'' || chr == '`' || chr == '"')
{
r.x += 3;
r.w = 2;
r.h = 2;
}
if (chr == 'o' || chr == 'O' || chr == '0')
DrawLinedRect(r);
else
DrawFilledRect(r);
}
}
Gwen::Point Base::MeasureText(Gwen::Font* pFont, const Gwen::UnicodeString& text)
{
Gwen::Point p;
p.x = pFont->size * Scale() * (float)text.length() * 0.4;
p.y = pFont->size * Scale();
return p;
}
} // namespace Renderer
} // namespace Gwen

View file

@ -0,0 +1,117 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_BASERENDER_H
#define GWEN_BASERENDER_H
#include "Gwen/Structures.h"
namespace Gwen
{
struct Font;
struct Texture;
namespace Renderer
{
class Base;
class ICacheToTexture
{
public:
virtual void Initialize() = 0;
virtual void ShutDown() = 0;
virtual void SetupCacheTexture(Gwen::Controls::Base* control) = 0;
virtual void FinishCacheTexture(Gwen::Controls::Base* control) = 0;
virtual void DrawCachedControlTexture(Gwen::Controls::Base* control) = 0;
virtual void CreateControlCacheTexture(Gwen::Controls::Base* control) = 0;
virtual void UpdateControlCacheTexture(Gwen::Controls::Base* control) = 0;
virtual void SetRenderer(Gwen::Renderer::Base* renderer) = 0;
};
class GWEN_EXPORT Base
{
public:
Base();
virtual ~Base();
virtual void Begin(){};
virtual void End(){};
virtual void SetDrawColor(Color color){};
virtual void DrawLine(int x, int y, int a, int b){};
virtual void DrawFilledRect(Gwen::Rect rect){};
;
virtual void StartClip(){};
virtual void EndClip(){};
virtual void LoadTexture(Gwen::Texture* pTexture){};
virtual void FreeTexture(Gwen::Texture* pTexture){};
virtual void DrawTexturedRect(Gwen::Texture* pTexture, Gwen::Rect pTargetRect, float u1 = 0.0f, float v1 = 0.0f, float u2 = 1.0f, float v2 = 1.0f){};
virtual void DrawMissingImage(Gwen::Rect pTargetRect);
virtual ICacheToTexture* GetCTT() { return NULL; }
virtual void LoadFont(Gwen::Font* pFont){};
virtual void FreeFont(Gwen::Font* pFont){};
virtual void RenderText(Gwen::Font* pFont, Gwen::Point pos, const Gwen::UnicodeString& text);
virtual Gwen::Point MeasureText(Gwen::Font* pFont, const Gwen::UnicodeString& text);
//
// No need to implement these functions in your derived class, but if
// you can do them faster than the default implementation it's a good idea to.
//
virtual void DrawLinedRect(Gwen::Rect rect);
virtual void DrawPixel(int x, int y);
virtual void DrawShavedCornerRect(Gwen::Rect rect, bool bSlight = false);
virtual Gwen::Point MeasureText(Gwen::Font* pFont, const Gwen::String& text);
virtual void RenderText(Gwen::Font* pFont, Gwen::Point pos, const Gwen::String& text);
virtual void Resize(int width, int height) = 0;
public:
//
// Translate a panel's local drawing coordinate
// into view space, taking Offset's into account.
//
void Translate(int& x, int& y);
void Translate(Gwen::Rect& rect);
//
// Set the rendering offset. You shouldn't have to
// touch these, ever.
//
void SetRenderOffset(const Gwen::Point& offset) { m_RenderOffset = offset; }
void AddRenderOffset(const Gwen::Rect& offset)
{
m_RenderOffset.x += offset.x;
m_RenderOffset.y += offset.y;
}
const Gwen::Point& GetRenderOffset() const { return m_RenderOffset; }
private:
Gwen::Point m_RenderOffset;
public:
void SetClipRegion(Gwen::Rect rect);
void AddClipRegion(Gwen::Rect rect);
bool ClipRegionVisible();
const Gwen::Rect& ClipRegion() const;
private:
Gwen::Rect m_rectClipRegion;
public:
void SetScale(float fScale) { m_fScale = fScale; }
float Scale() const { return m_fScale; }
float m_fScale;
};
} // namespace Renderer
} // namespace Gwen
#endif

View file

@ -0,0 +1,34 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/glad
)
IF(NOT WIN32 AND NOT APPLE)
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/optionalX11
)
ADD_DEFINITIONS(-DGLEW_STATIC)
ADD_DEFINITIONS("-DGLEW_INIT_OPENGL11_FUNCTIONS=1")
ADD_DEFINITIONS("-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1")
ADD_DEFINITIONS("-DDYNAMIC_LOAD_X11_FUNCTIONS=1")
ENDIF()
ADD_DEFINITIONS( -DGLEW_STATIC -DGWEN_COMPILE_STATIC -D_HAS_EXCEPTIONS=0 )
FILE(GLOB gwen_SRCS "*.cpp" "Controls/*.cpp" "Controls/Dialog/*.cpp" "Controls/Dialogs/*.cpp" "Controls/Layout/*.cpp" "Controls/Property/*.cpp" "Input/*.cpp" "Platforms/*.cpp" "Renderers/*.cpp" "Skins/*.cpp")
FILE(GLOB gwen_HDRS "*.h" "Controls/*.h" "Controls/Dialog/*.h" "Controls/Dialogs/*.h" "Controls/Layout/*.h" "Controls/Property/*.h" "Input/*.h" "Platforms/*.h" "Renderers/*.h" "Skins/*.h")
ADD_LIBRARY(gwen ${gwen_SRCS} ${gwen_HDRS})
IF (BUILD_SHARED_LIBS)
IF(WIN32 OR APPLE)
target_link_libraries(gwen ${OPENGL_gl_LIBRARY})
ENDIF()
ENDIF()
INSTALL(TARGETS gwen
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})

View file

@ -0,0 +1,16 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONFIG_H
#define GWEN_CONFIG_H
//
// Disables animation functions.
//
//#define GWEN_NO_ANIMATION
#endif

View file

@ -0,0 +1,10 @@
#pragma once
#ifndef GWEN_CONTROLS_H
#define GWEN_CONTROLS_H
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/TextBox.h"
#include "Gwen/Anim.h"
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,510 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_BASE_H
#define GWEN_CONTROLS_BASE_H
#include "Gwen/Exports.h"
#include "Gwen/Structures.h"
#include "Gwen/BaseRender.h"
#include "Gwen/Events.h"
#include <list>
#include <map>
#define GWEN_DECLARE_CAST(T) \
virtual class T* DynamicCast##T() { return 0; } \
virtual const class T* DynamicCast##T() const { return 0; }
#define GWEN_IMPLEMENT_CAST(T) \
virtual class T* DynamicCast##T() { return (T*)this; } \
virtual const class T* DynamicCast##T() const { return (T*)this; }
namespace Gwen
{
namespace ControlsInternal
{
class ColorDisplay;
class Resizer;
}; // namespace ControlsInternal
namespace Pos
{
enum
{
None = 0,
Left = (1 << 1),
Right = (1 << 2),
Top = (1 << 3),
Bottom = (1 << 4),
CenterV = (1 << 5),
CenterH = (1 << 6),
Fill = (1 << 7),
Center = CenterV | CenterH,
};
}
namespace Skin
{
class Base;
}
namespace Controls
{
class Canvas;
namespace Layout
{
class TableRow;
};
class GWEN_EXPORT Base : public Event::Handler
{
public:
GWEN_DECLARE_CAST(TabButton)
GWEN_DECLARE_CAST(DockedTabControl)
virtual class Layout::TableRow* DynamicCastLayoutTableRow() { return 0; }
virtual const class Layout::TableRow* DynamicCastLayoutTableRow() const { return 0; }
GWEN_DECLARE_CAST(TextBoxNumeric)
GWEN_DECLARE_CAST(HorizontalSlider)
GWEN_DECLARE_CAST(DockBase)
GWEN_DECLARE_CAST(MenuItem)
GWEN_DECLARE_CAST(PropertyRow)
GWEN_DECLARE_CAST(WindowControl)
GWEN_DECLARE_CAST(TreeControl)
GWEN_DECLARE_CAST(TreeNode)
GWEN_DECLARE_CAST(HSVColorPicker)
GWEN_DECLARE_CAST(TabControl)
GWEN_DECLARE_CAST(TabControlInner)
GWEN_DECLARE_CAST(GroupBox)
GWEN_DECLARE_CAST(Properties)
GWEN_DECLARE_CAST(RadioButton)
GWEN_DECLARE_CAST(LabeledRadioButton)
virtual class ::Gwen::ControlsInternal::Resizer* DynamicCastResizer() { return 0; }
virtual const class ::Gwen::ControlsInternal::Resizer* DynamicCastResizer() const { return 0; }
virtual class ::Gwen::ControlsInternal::ColorDisplay* DynamicCastColorDisplay() { return 0; }
virtual const class ::Gwen::ControlsInternal::ColorDisplay* DynamicCastColorDisplay() const { return 0; }
typedef std::list<Base*> List;
typedef std::map<Gwen::UnicodeString, Gwen::Event::Caller*> AccelMap;
Base(Base* pParent);
virtual ~Base();
virtual void DelayedDelete();
virtual void SetParent(Controls::Base* pParent);
virtual Controls::Base* GetParent() const { return m_Parent; }
virtual Controls::Canvas* GetCanvas();
virtual Base::List& GetChildren()
{
if (m_InnerPanel) return m_InnerPanel->GetChildren();
return Children;
}
virtual bool IsChild(Controls::Base* pChild);
virtual int NumChildren();
virtual bool SizeToChildren(bool w = true, bool h = true);
virtual Gwen::Point ChildrenSize();
virtual Controls::Base* FindChildByName(const Gwen::String& name, bool bRecursive = false);
virtual void SetName(Gwen::String name) { m_Name = name; }
virtual const Gwen::String& GetName() { return m_Name; }
virtual void Think() {}
virtual void ExpandAll() {}
virtual void SizeToContents() {}
virtual bool IsActive() { return false; }
virtual void AddChild(Controls::Base* pChild);
virtual void RemoveChild(Controls::Base* pParent);
protected:
virtual void OnChildAdded(Controls::Base* pChild);
virtual void OnChildRemoved(Controls::Base* pChild);
public:
virtual void RemoveAllChildren();
virtual void SendToBack(void);
virtual void BringToFront(void);
virtual void BringNextToControl(Controls::Base* pChild, bool bBehind);
virtual Gwen::Point LocalPosToCanvas(const Gwen::Point& in);
virtual Gwen::Point CanvasPosToLocal(const Gwen::Point& in);
virtual void Dock(int iDock);
virtual int GetDock();
virtual void RestrictToParent(bool restrict) { m_bRestrictToParent = restrict; }
virtual bool ShouldRestrictToParent() { return m_bRestrictToParent; }
virtual int X() const
{
return m_Bounds.x;
}
virtual int Y() const
{
return m_Bounds.y;
}
virtual int Width() const
{
return m_Bounds.w;
}
virtual int Height() const
{
return m_Bounds.h;
}
virtual int Bottom() const
{
return m_Bounds.y + m_Bounds.h + m_Margin.bottom;
}
virtual int Right() const
{
return m_Bounds.x + m_Bounds.w + m_Margin.right;
}
virtual const Margin& GetMargin() const { return m_Margin; }
virtual const Padding& GetPadding() const { return m_Padding; }
virtual void SetPos(int x, int y);
virtual void SetWidth(int w)
{
SetSize(w, Height());
}
virtual void SetHeight(int h)
{
SetSize(Width(), h);
}
virtual bool SetSize(int w, int h);
virtual bool SetBounds(int x, int y, int w, int h);
virtual bool SetBounds(const Gwen::Rect& bounds);
virtual void SetPadding(const Padding& padding);
virtual void SetMargin(const Margin& margin);
// MoveTo is identical to SetPos except it uses ShouldRestrictToParent()
virtual void MoveTo(int x, int y);
virtual void MoveBy(int x, int y);
virtual const Gwen::Rect& GetBounds() const
{
return m_Bounds;
}
virtual Controls::Base* GetControlAt(int x, int y);
protected:
virtual void OnBoundsChanged(Gwen::Rect oldBounds);
virtual void OnChildBoundsChanged(Gwen::Rect oldChildBounds, Base* pChild);
virtual void OnScaleChanged();
public:
// Innerbounds is the area inside the control that
// doesn't have child controls docked to it.
virtual const Gwen::Rect& GetInnerBounds() const { return m_InnerBounds; }
protected:
Gwen::Rect m_InnerBounds;
public:
virtual const Gwen::Rect& GetRenderBounds() const { return m_RenderBounds; }
protected:
virtual void UpdateRenderBounds();
public:
virtual void DoRender(Gwen::Skin::Base* skin);
virtual void DoCacheRender(Gwen::Skin::Base* skin, Gwen::Controls::Base* pMaster);
protected:
virtual void Render(Gwen::Skin::Base* skin);
virtual void RenderUnder(Gwen::Skin::Base* /*skin*/){};
virtual void RenderOver(Gwen::Skin::Base* /*skin*/){};
virtual void RenderFocus(Gwen::Skin::Base* /*skin*/);
public:
virtual void SetHidden(bool hidden)
{
if (m_bHidden == hidden)
return;
m_bHidden = hidden;
Invalidate();
}
virtual bool Hidden() const; // Returns true only if this control is hidden
virtual bool Visible() const; // Returns false if this control or its parents are hidden
virtual void Hide() { SetHidden(true); }
virtual void Show() { SetHidden(false); }
//Skin
virtual void SetSkin(Skin::Base* skin, bool doChildren = false);
virtual Gwen::Skin::Base* GetSkin(void);
// Background drawing
virtual bool ShouldDrawBackground() { return m_bDrawBackground; }
virtual void SetShouldDrawBackground(bool b) { m_bDrawBackground = b; }
protected:
virtual void OnSkinChanged(Gwen::Skin::Base* newSkin);
public:
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);
virtual bool OnMouseWheeled(int iDelta);
virtual void OnMouseClickLeft(int /*x*/, int /*y*/, bool /*bDown*/){};
virtual void OnMouseClickRight(int /*x*/, int /*y*/, bool /*bDown*/) {}
virtual void OnMouseDoubleClickLeft(int x, int y) { OnMouseClickLeft(x, y, true); };
virtual void OnMouseDoubleClickRight(int x, int y) { OnMouseClickRight(x, y, true); };
virtual void OnLostKeyboardFocus() {}
virtual void OnKeyboardFocus() {}
virtual void SetMouseInputEnabled(bool b) { m_bMouseInputEnabled = b; }
virtual bool GetMouseInputEnabled() { return m_bMouseInputEnabled; }
virtual void SetKeyboardInputEnabled(bool b) { m_bKeyboardInputEnabled = b; }
virtual bool GetKeyboardInputEnabled() const { return m_bKeyboardInputEnabled; }
virtual bool NeedsInputChars() { return false; }
virtual bool OnChar(Gwen::UnicodeChar /*c*/) { return false; }
virtual bool OnKeyPress(int iKey, bool bPress = true);
virtual bool OnKeyRelease(int iKey);
virtual void OnPaste(Controls::Base* /*pFrom*/) {}
virtual void OnCopy(Controls::Base* /*pFrom*/) {}
virtual void OnCut(Controls::Base* /*pFrom*/) {}
virtual void OnSelectAll(Controls::Base* /*pFrom*/) {}
virtual bool OnKeyTab(bool bDown);
virtual bool OnKeySpace(bool /*bDown*/) { return false; }
virtual bool OnKeyReturn(bool /*bDown*/) { return false; }
virtual bool OnKeyBackspace(bool /*bDown*/) { return false; }
virtual bool OnKeyDelete(bool /*bDown*/) { return false; }
virtual bool OnKeyRight(bool /*bDown*/) { return false; }
virtual bool OnKeyLeft(bool /*bDown*/) { return false; }
virtual bool OnKeyHome(bool /*bDown*/) { return false; }
virtual bool OnKeyEnd(bool /*bDown*/) { return false; }
virtual bool OnKeyUp(bool /*bDown*/) { return false; }
virtual bool OnKeyDown(bool /*bDown*/) { return false; }
virtual bool OnKeyEscape(bool /*bDown*/) { return false; }
virtual void OnMouseEnter();
virtual void OnMouseLeave();
virtual bool IsHovered();
virtual bool ShouldDrawHover();
virtual void Touch();
virtual void OnChildTouched(Controls::Base* pChild);
virtual bool IsOnTop();
virtual bool HasFocus();
virtual void Focus();
virtual void Blur();
//Other
virtual void SetDisabled(bool active) { m_bDisabled = active; }
virtual bool IsDisabled() { return m_bDisabled; }
virtual void Redraw()
{
m_bCacheTextureDirty = true;
if (m_Parent) m_Parent->Redraw();
}
virtual void SetCacheToTexture() { m_bCacheToTexture = true; }
virtual bool ShouldCacheToTexture() { return m_bCacheToTexture; }
virtual void SetCursor(unsigned char c) { m_Cursor = c; }
virtual void UpdateCursor();
virtual Gwen::Point GetMinimumSize() { return Gwen::Point(1, 1); }
virtual Gwen::Point GetMaximumSize() { return Gwen::Point(4096, 4096); }
virtual void SetToolTip(const String& strText);
virtual void SetToolTip(const UnicodeString& strText);
virtual void SetToolTip(Base* tooltip)
{
m_ToolTip = tooltip;
if (m_ToolTip)
{
m_ToolTip->SetParent(this);
m_ToolTip->SetHidden(true);
}
}
virtual Base* GetToolTip() { return m_ToolTip; }
virtual bool IsMenuComponent();
virtual void CloseMenus();
virtual bool IsTabable() { return m_Tabable; }
virtual void SetTabable(bool isTabable) { m_Tabable = isTabable; }
//Accelerator functionality
void DefaultAccel(Gwen::Controls::Base* /*pCtrl*/) { AcceleratePressed(); }
virtual void AcceleratePressed(){};
virtual bool AccelOnlyFocus() { return false; }
virtual bool HandleAccelerator(Gwen::UnicodeString& accelerator);
template <typename T>
void AddAccelerator(Gwen::UnicodeString accelerator, T func, Gwen::Event::Handler* handler = NULL)
{
if (handler == NULL)
handler = this;
Gwen::Event::Caller* caller = new Gwen::Event::Caller();
caller->Add(handler, func);
m_Accelerators[accelerator] = caller;
}
void AddAccelerator(Gwen::UnicodeString accelerator)
{
AddAccelerator(accelerator, &Base::DefaultAccel, this);
}
AccelMap m_Accelerators;
// Default Events
Gwen::Event::Caller onHoverEnter;
Gwen::Event::Caller onHoverLeave;
// Childrens List
Base::List Children;
protected:
// The logical parent
// It's usually what you expect, the control you've parented it to.
Base* m_Parent;
// If the innerpanel exists our children will automatically
// become children of that instead of us - allowing us to move
// them all around by moving that panel (useful for scrolling etc)
Base* m_InnerPanel;
// This is the panel's actual parent - most likely the logical
// parent's InnerPanel (if it has one). You should rarely need this.
Base* m_ActualParent;
Base* m_ToolTip;
Skin::Base* m_Skin;
Gwen::Rect m_Bounds;
Gwen::Rect m_RenderBounds;
Padding m_Padding;
Margin m_Margin;
Gwen::String m_Name;
bool m_bRestrictToParent;
bool m_bDisabled;
bool m_bHidden;
bool m_bMouseInputEnabled;
bool m_bKeyboardInputEnabled;
bool m_bDrawBackground;
int m_iDock;
unsigned char m_Cursor;
bool m_Tabable;
public:
bool NeedsLayout() { return m_bNeedsLayout; }
void Invalidate();
void InvalidateParent()
{
if (m_Parent)
{
m_Parent->Invalidate();
}
}
void InvalidateChildren(bool bRecursive = false);
void Position(int pos, int xpadding = 0, int ypadding = 0);
protected:
virtual void RecurseLayout(Skin::Base* skin);
virtual void Layout(Skin::Base* skin);
virtual void PostLayout(Skin::Base* /*skin*/){};
bool m_bNeedsLayout;
bool m_bCacheTextureDirty;
bool m_bCacheToTexture;
//
// Drag + Drop
public:
// Giver
virtual void DragAndDrop_SetPackage(bool bDraggable, const String& strName = "", void* pUserData = NULL);
virtual bool DragAndDrop_Draggable();
virtual bool DragAndDrop_ShouldStartDrag() { return true; }
virtual void DragAndDrop_StartDragging(Gwen::DragAndDrop::Package* pPackage, int x, int y);
virtual Gwen::DragAndDrop::Package* DragAndDrop_GetPackage(int x, int y);
virtual void DragAndDrop_EndDragging(bool /*bSuccess*/, int /*x*/, int /*y*/){};
protected:
DragAndDrop::Package* m_DragAndDrop_Package;
public:
// Receiver
virtual void DragAndDrop_HoverEnter(Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/) {}
virtual void DragAndDrop_HoverLeave(Gwen::DragAndDrop::Package* /*pPackage*/) {}
virtual void DragAndDrop_Hover(Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/){};
virtual bool DragAndDrop_HandleDrop(Gwen::DragAndDrop::Package* pPackage, int x, int y);
virtual bool DragAndDrop_CanAcceptPackage(Gwen::DragAndDrop::Package* /*pPackage*/) { return false; }
//
// This is to be used by the client implementation
// NOT HOOKS ETC.
//
public:
void* GetUserData() { return m_pUserData; }
void SetUserData(void* pData) { m_pUserData = pData; }
private:
void* m_pUserData;
//
// Useful anim shortcuts
//
public:
#ifndef GWEN_NO_ANIMATION
virtual void Anim_WidthIn(float fLength, float fDelay = 0.0f, float fEase = 1.0f);
virtual void Anim_HeightIn(float fLength, float fDelay = 0.0f, float fEase = 1.0f);
virtual void Anim_WidthOut(float fLength, bool bHide = true, float fDelay = 0.0f, float fEase = 1.0f);
virtual void Anim_HeightOut(float fLength, bool bHide = true, float fDelay = 0.0f, float fEase = 1.0f);
#endif
};
} // namespace Controls
} // namespace Gwen
// To be placed in the controls .h definition.
#define GWEN_CONTROL(ThisName, BaseName) \
public: \
typedef BaseName BaseClass; \
typedef ThisName ThisClass; \
GWEN_IMPLEMENT_CAST(ThisName); \
ThisName(Gwen::Controls::Base* pParent)
#define GWEN_CONTROL_INLINE(ThisName, BaseName) \
GWEN_CONTROL(ThisName, BaseName) : BaseClass(pParent)
#define GWEN_CONTROL_CONSTRUCTOR(ThisName) \
ThisName::ThisName(Gwen::Controls::Base* pParent) : BaseClass(pParent)
#endif

View file

@ -0,0 +1,166 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/ImagePanel.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(Button)
{
m_Image = NULL;
m_bDepressed = false;
m_bCenterImage = false;
SetSize(100, 20);
SetMouseInputEnabled(true);
SetIsToggle(false);
SetAlignment(Gwen::Pos::Center);
SetTextPadding(Padding(3, 0, 3, 0));
m_bToggleStatus = false;
SetKeyboardInputEnabled(false);
SetTabable(false);
}
void Button::Render(Skin::Base* skin)
{
if (ShouldDrawBackground())
{
bool bDrawDepressed = IsDepressed() && IsHovered();
if (IsToggle()) bDrawDepressed = bDrawDepressed || GetToggleState();
bool bDrawHovered = IsHovered() && ShouldDrawHover();
skin->DrawButton(this, bDrawDepressed, bDrawHovered);
}
}
void Button::OnMouseClickLeft(int /*x*/, int /*y*/, bool bDown)
{
if (bDown)
{
m_bDepressed = true;
Gwen::MouseFocus = this;
onDown.Call(this);
}
else
{
if (IsHovered() && m_bDepressed)
{
OnPress();
}
m_bDepressed = false;
Gwen::MouseFocus = NULL;
onUp.Call(this);
}
Redraw();
}
void Button::OnPress()
{
if (IsToggle())
{
SetToggleState(!GetToggleState());
}
onPress.Call(this);
}
void Button::SetImage(const TextObject& strName, bool bCenter)
{
if (strName.GetUnicode() == L"")
{
if (m_Image)
{
delete m_Image;
m_Image = NULL;
}
return;
}
if (!m_Image)
{
m_Image = new ImagePanel(this);
}
m_Image->SetImage(strName);
m_Image->SizeToContents();
m_Image->SetPos(m_Padding.left, 2);
m_bCenterImage = bCenter;
int IdealTextPadding = m_Image->Right() + m_Padding.left + 4;
if (m_rTextPadding.left < IdealTextPadding)
{
m_rTextPadding.left = IdealTextPadding;
}
}
void Button::SetToggleState(bool b)
{
if (m_bToggleStatus == b) return;
m_bToggleStatus = b;
onToggle.Call(this);
if (m_bToggleStatus)
{
onToggleOn.Call(this);
}
else
{
onToggleOff.Call(this);
}
}
void Button::SizeToContents()
{
BaseClass::SizeToContents();
if (m_Image)
{
int height = m_Image->Height() + 4;
if (Height() < height)
{
SetHeight(height);
}
}
}
bool Button::OnKeySpace(bool bDown)
{
OnMouseClickLeft(0, 0, bDown);
return true;
}
void Button::AcceleratePressed()
{
OnPress();
}
void Button::Layout(Skin::Base* pSkin)
{
BaseClass::Layout(pSkin);
if (m_Image)
{
Gwen::Align::CenterVertically(m_Image);
if (m_bCenterImage)
Gwen::Align::CenterHorizontally(m_Image);
}
}
void Button::OnMouseDoubleClickLeft(int x, int y)
{
OnMouseClickLeft(x, y, true);
onDoubleClick.Call(this);
};

View file

@ -0,0 +1,86 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_BUTTON_H
#define GWEN_CONTROLS_BUTTON_H
#include "Gwen/TextObject.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
namespace Gwen
{
namespace Controls
{
class ImagePanel;
class GWEN_EXPORT Button : public Label
{
public:
GWEN_CONTROL(Button, Label);
virtual void Render(Skin::Base* skin);
virtual void OnMouseClickLeft(int x, int y, bool bDown);
virtual void OnMouseDoubleClickLeft(int x, int y);
virtual bool OnKeySpace(bool bDown);
virtual void OnPress();
virtual void AcceleratePressed();
virtual bool IsDepressed() const { return m_bDepressed; }
//
// Buttons can be toggle type, which means that it is
// toggled on and off. Its toggle status is in IsDepressed.
//
virtual void SetIsToggle(bool b) { m_bToggle = b; }
virtual bool IsToggle() const { return m_bToggle; }
virtual bool GetToggleState() const { return m_bToggleStatus; }
virtual void SetToggleState(bool b);
virtual void Toggle() { SetToggleState(!GetToggleState()); }
virtual void SetImage(const TextObject& strName, bool bCenter = false);
// You can use this to trigger OnPress directly from other controls using GWEN_CALL_EX
virtual void ReceiveEventPress(Base* /*pControl*/)
{
OnPress();
}
virtual void SizeToContents();
virtual void Layout(Skin::Base* pSkin);
virtual bool OnKeyReturn(bool bDown)
{
onKeyboardReturn.Call(this);
return true;
}
public:
Gwen::Event::Caller onPress;
Gwen::Event::Caller onDown;
Gwen::Event::Caller onUp;
Gwen::Event::Caller onDoubleClick;
Gwen::Event::Caller onKeyboardReturn;
Gwen::Event::Caller onToggle;
Gwen::Event::Caller onToggleOn;
Gwen::Event::Caller onToggleOff;
protected:
ImagePanel* m_Image;
bool m_bDepressed;
bool m_bToggle;
bool m_bToggleStatus;
bool m_bCenterImage;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,227 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Canvas.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Menu.h"
#include "Gwen/DragAndDrop.h"
#include "Gwen/ToolTip.h"
#ifndef GWEN_NO_ANIMATION
#include "Gwen/Anim.h"
#endif
using namespace Gwen::Controls;
Canvas::Canvas(Gwen::Skin::Base* pSkin) : BaseClass(NULL), m_bAnyDelete(false), m_fScale(-1)
{
SetBounds(0, 0, 10000, 10000);
SetSkin(pSkin);
SetScale(1.0f);
SetBackgroundColor(Color(255, 255, 255, 255));
SetDrawBackground(false);
}
void Canvas::RenderCanvas()
{
DoThink();
Gwen::Renderer::Base* render = m_Skin->GetRender();
render->Begin();
RecurseLayout(m_Skin);
render->SetClipRegion(GetBounds());
render->SetRenderOffset(Gwen::Point(0, 0));
render->SetScale(Scale());
if (m_bDrawBackground)
{
render->SetDrawColor(m_BackgroundColor);
render->DrawFilledRect(GetRenderBounds());
}
DoRender(m_Skin);
DragAndDrop::RenderOverlay(this, m_Skin);
ToolTip::RenderToolTip(m_Skin);
render->EndClip();
render->End();
ProcessDelayedDeletes();
}
void Canvas::Render(Gwen::Skin::Base* /*pRender*/)
{
m_bNeedsRedraw = false;
}
void Canvas::OnBoundsChanged(Gwen::Rect oldBounds)
{
BaseClass::OnBoundsChanged(oldBounds);
InvalidateChildren(true);
}
void Canvas::DoThink()
{
if (Hidden()) return;
#ifndef GWEN_NO_ANIMATION
Gwen::Anim::Think();
#endif
// Reset tabbing
{
NextTab = NULL;
FirstTab = NULL;
}
ProcessDelayedDeletes();
// Check has focus etc..
RecurseLayout(m_Skin);
// If we didn't have a next tab, cycle to the start.
if (NextTab == NULL)
NextTab = FirstTab;
Gwen::Input::OnCanvasThink(this);
}
void Canvas::SetScale(float f)
{
if (m_fScale == f) return;
m_fScale = f;
if (m_Skin && m_Skin->GetRender())
m_Skin->GetRender()->SetScale(m_fScale);
OnScaleChanged();
Redraw();
}
void Canvas::AddDelayedDelete(Gwen::Controls::Base* pControl)
{
if (!m_bAnyDelete || m_DeleteSet.find(pControl) == m_DeleteSet.end())
{
m_bAnyDelete = true;
m_DeleteSet.insert(pControl);
m_DeleteList.push_back(pControl);
}
}
void Canvas::PreDelete(Controls::Base* pControl)
{
if (m_bAnyDelete)
{
std::set<Controls::Base*>::iterator itFind;
if ((itFind = m_DeleteSet.find(pControl)) != m_DeleteSet.end())
{
m_DeleteList.remove(pControl);
m_DeleteSet.erase(pControl);
m_bAnyDelete = !m_DeleteSet.empty();
}
}
}
void Canvas::ProcessDelayedDeletes()
{
while (m_bAnyDelete)
{
m_bAnyDelete = false;
Controls::Base::List deleteList = m_DeleteList;
m_DeleteList.clear();
m_DeleteSet.clear();
for (Gwen::Controls::Base::List::iterator it = deleteList.begin(); it != deleteList.end(); ++it)
{
Gwen::Controls::Base* pControl = *it;
delete pControl;
}
}
}
void Canvas::Release()
{
Base::List::iterator iter = Children.begin();
while (iter != Children.end())
{
Base* pChild = *iter;
iter = Children.erase(iter);
delete pChild;
}
delete this;
}
bool Canvas::InputMouseMoved(int x, int y, int deltaX, int deltaY)
{
if (Hidden()) return false;
// Todo: Handle scaling here..
//float fScale = 1.0f / Scale();
Gwen::Input::OnMouseMoved(this, x, y, deltaX, deltaY);
if (!Gwen::HoveredControl) return false;
if (Gwen::HoveredControl == this) return false;
if (Gwen::HoveredControl->GetCanvas() != this) return false;
Gwen::HoveredControl->OnMouseMoved(x, y, deltaX, deltaY);
Gwen::HoveredControl->UpdateCursor();
DragAndDrop::OnMouseMoved(Gwen::HoveredControl, x, y);
return true;
}
bool Canvas::InputMouseButton(int iButton, bool bDown)
{
if (Hidden()) return false;
return Gwen::Input::OnMouseClicked(this, iButton, bDown);
}
bool Canvas::InputKey(int iKey, bool bDown)
{
if (Hidden()) return false;
if (iKey <= Gwen::Key::Invalid) return false;
if (iKey >= Gwen::Key::Count) return false;
return Gwen::Input::OnKeyEvent(this, iKey, bDown);
}
bool Canvas::InputCharacter(Gwen::UnicodeChar chr)
{
if (Hidden()) return false;
if (!iswprint(chr)) return false;
//Handle Accelerators
if (Gwen::Input::HandleAccelerator(this, chr))
return true;
//Handle characters
if (!Gwen::KeyboardFocus) return false;
if (Gwen::KeyboardFocus->GetCanvas() != this) return false;
if (!Gwen::KeyboardFocus->Visible()) return false;
if (Gwen::Input::IsControlDown()) return false;
return KeyboardFocus->OnChar(chr);
}
bool Canvas::InputMouseWheel(int val)
{
if (Hidden()) return false;
if (!Gwen::HoveredControl) return false;
if (Gwen::HoveredControl == this) return false;
if (Gwen::HoveredControl->GetCanvas() != this) return false;
return Gwen::HoveredControl->OnMouseWheeled(val);
}

View file

@ -0,0 +1,103 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_CANVAS_H
#define GWEN_CONTROLS_CANVAS_H
#include <set>
#include "Gwen/Controls/Base.h"
#include "Gwen/InputHandler.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT Canvas : public Base
{
public:
typedef Controls::Base BaseClass;
Canvas(Skin::Base* pSkin);
//
// For additional initialization
// (which is sometimes not appropriate in the constructor)
//
virtual void Initialize(){};
//
// You should call this to render your canvas.
//
virtual void RenderCanvas();
//
// Call this whenever you want to process input. This
// is usually once a frame..
//
virtual void DoThink();
//
// In most situations you will be rendering the canvas
// every frame. But in some situations you will only want
// to render when there have been changes. You can do this
// by checking NeedsRedraw().
//
virtual bool NeedsRedraw() { return m_bNeedsRedraw; }
virtual void Redraw() { m_bNeedsRedraw = true; }
// Internal. Do not call directly.
virtual void Render(Skin::Base* pRender);
// Childpanels call parent->GetCanvas() until they get to
// this top level function.
virtual Controls::Canvas* GetCanvas() { return this; }
virtual void SetScale(float f);
virtual float Scale() const { return m_fScale; }
virtual void OnBoundsChanged(Gwen::Rect oldBounds);
//
// Call this to delete the canvas, and its children
// in the right order.
//
virtual void Release();
// Delayed deletes
virtual void AddDelayedDelete(Controls::Base* pControl);
virtual void ProcessDelayedDeletes();
Controls::Base* FirstTab;
Controls::Base* NextTab;
// Input
virtual bool InputMouseMoved(int x, int y, int deltaX, int deltaY);
virtual bool InputMouseButton(int iButton, bool bDown);
virtual bool InputKey(int iKey, bool bDown);
virtual bool InputCharacter(Gwen::UnicodeChar chr);
virtual bool InputMouseWheel(int val);
// Background
virtual void SetBackgroundColor(const Gwen::Color& color) { m_BackgroundColor = color; }
virtual void SetDrawBackground(bool bShouldDraw) { m_bDrawBackground = bShouldDraw; }
private:
bool m_bNeedsRedraw;
bool m_bAnyDelete;
float m_fScale;
Controls::Base::List m_DeleteList;
std::set<Controls::Base*> m_DeleteSet;
friend class Controls::Base;
void PreDelete(Controls::Base*);
bool m_bDrawBackground;
Gwen::Color m_BackgroundColor;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,53 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/CheckBox.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(CheckBox)
{
SetSize(13, 13);
m_bChecked = true;
Toggle();
}
void CheckBox::Render(Skin::Base* skin)
{
skin->DrawCheckBox(this, m_bChecked, IsDepressed());
}
void CheckBox::OnPress()
{
if (IsChecked() && !AllowUncheck())
return;
Toggle();
}
void CheckBox::OnCheckStatusChanged()
{
if (IsChecked())
{
onChecked.Call(this);
}
else
{
onUnChecked.Call(this);
}
onCheckChanged.Call(this);
}
void CheckBox::SetChecked(bool bChecked)
{
if (m_bChecked == bChecked) return;
m_bChecked = bChecked;
OnCheckStatusChanged();
}

View file

@ -0,0 +1,81 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_CHECKBOX_H
#define GWEN_CONTROLS_CHECKBOX_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Symbol.h"
#include "Gwen/Controls/LabelClickable.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT CheckBox : public Button
{
public:
GWEN_CONTROL(CheckBox, Button);
virtual void Render(Skin::Base* skin);
virtual void OnPress();
virtual void SetChecked(bool Checked);
virtual void Toggle() { SetChecked(!IsChecked()); }
virtual bool IsChecked() { return m_bChecked; }
Gwen::Event::Caller onChecked;
Gwen::Event::Caller onUnChecked;
Gwen::Event::Caller onCheckChanged;
private:
// For derived controls
virtual bool AllowUncheck() { return true; }
void OnCheckStatusChanged();
bool m_bChecked;
};
class GWEN_EXPORT CheckBoxWithLabel : public Base
{
public:
GWEN_CONTROL_INLINE(CheckBoxWithLabel, Base)
{
SetSize(200, 19);
m_Checkbox = new CheckBox(this);
m_Checkbox->Dock(Pos::Left);
m_Checkbox->SetMargin(Margin(0, 3, 3, 3));
m_Checkbox->SetTabable(false);
m_Label = new LabelClickable(this);
m_Label->Dock(Pos::Fill);
m_Label->onPress.Add(m_Checkbox, &CheckBox::ReceiveEventPress);
m_Label->SetTabable(false);
SetTabable(false);
}
virtual CheckBox* Checkbox() { return m_Checkbox; }
virtual LabelClickable* Label() { return m_Label; }
virtual bool OnKeySpace(bool bDown)
{
if (bDown) m_Checkbox->SetChecked(!m_Checkbox->IsChecked());
return true;
}
private:
CheckBox* m_Checkbox;
LabelClickable* m_Label;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,317 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Utility.h"
#include "Gwen/Controls/ColorControls.h"
using namespace Gwen;
using namespace Gwen::Controls;
//Find a place to put these...
Color HSVToColor(float h, float s, float v)
{
if (h < 0.0f) h += 360.0f;
if (h > 360.0f) h -= 360.0f;
s *= 255.0f;
v *= 255.0f;
float r, g, b;
if (!h && !s)
{
r = g = b = v;
}
double min, max, delta, hue;
max = v;
delta = (max * s) / 255.0;
min = max - delta;
hue = h;
if (h > 300 || h <= 60)
{
r = (int)max;
if (h > 300)
{
g = (int)min;
hue = (hue - 360.0) / 60.0;
b = (int)((hue * delta - min) * -1);
}
else
{
b = (int)min;
hue = hue / 60.0;
g = (int)(hue * delta + min);
}
}
else if (h > 60 && h < 180)
{
g = (int)max;
if (h < 120)
{
b = (int)min;
hue = (hue / 60.0 - 2.0) * delta;
r = (int)(min - hue);
}
else
{
r = (int)min;
hue = (hue / 60 - 2.0) * delta;
b = (int)(min + hue);
}
}
else
{
b = (int)max;
if (h < 240)
{
r = (int)min;
hue = (hue / 60.0 - 4.0) * delta;
g = (int)(min - hue);
}
else
{
g = (int)min;
hue = (hue / 60 - 4.0) * delta;
r = (int)(min + hue);
}
}
return Color(r, g, b, 255);
}
HSV RGBtoHSV(int r, int g, int b)
{
double min, max, delta, temp;
min = GwenUtil_Min(r, GwenUtil_Min(g, b));
max = GwenUtil_Max(r, GwenUtil_Max(g, b));
delta = max - min;
HSV hsv;
hsv.v = (int)max;
if (!delta)
{
hsv.h = hsv.s = 0;
}
else
{
temp = delta / max;
hsv.s = (int)(temp * 255);
if (r == (int)max)
{
temp = (double)(g - b) / delta;
}
else if (g == (int)max)
{
temp = 2.0 + ((double)(b - r) / delta);
}
else
{
temp = 4.0 + ((double)(r - g) / delta);
}
temp *= 60;
if (temp < 0)
{
temp += 360;
}
if (temp == 360)
{
temp = 0;
}
hsv.h = (int)temp;
}
hsv.s /= 255.0f;
hsv.v /= 255.0f;
return hsv;
}
GWEN_CONTROL_CONSTRUCTOR(ColorLerpBox)
{
SetColor(Gwen::Color(255, 128, 0, 255));
SetSize(128, 128);
SetMouseInputEnabled(true);
m_bDepressed = false;
}
//Find a place to put this? color member?
Gwen::Color LerpColor(Gwen::Color& toColor, Gwen::Color& fromColor, float amount)
{
Gwen::Color colorDelta = toColor - fromColor;
colorDelta.r *= amount;
colorDelta.g *= amount;
colorDelta.b *= amount;
Gwen::Color newColor = fromColor + colorDelta;
return newColor;
}
Gwen::Color ColorLerpBox::GetSelectedColor()
{
return GetColorAtPos(cursorPos.x, cursorPos.y);
}
void ColorLerpBox::SetColor(Gwen::Color color, bool onlyHue)
{
HSV hsv = RGBtoHSV(color.r, color.g, color.b);
m_Hue = hsv.h;
if (!onlyHue)
{
cursorPos.x = hsv.s * Width();
cursorPos.y = (1 - hsv.v) * Height();
}
onSelectionChanged.Call(this);
}
void ColorLerpBox::OnMouseMoved(int x, int y, int /*deltaX*/, int /*deltaY*/)
{
if (m_bDepressed)
{
cursorPos = CanvasPosToLocal(Gwen::Point(x, y));
//Do we have clamp?
if (cursorPos.x < 0)
cursorPos.x = 0;
if (cursorPos.x > Width())
cursorPos.x = Width();
if (cursorPos.y < 0)
cursorPos.y = 0;
if (cursorPos.y > Height())
cursorPos.y = Height();
onSelectionChanged.Call(this);
}
}
void ColorLerpBox::OnMouseClickLeft(int x, int y, bool bDown)
{
m_bDepressed = bDown;
if (bDown)
Gwen::MouseFocus = this;
else
Gwen::MouseFocus = NULL;
OnMouseMoved(x, y, 0, 0);
}
Gwen::Color ColorLerpBox::GetColorAtPos(int x, int y)
{
float xPercent = ((float)x / (float)Width());
float yPercent = 1 - ((float)y / (float)Height());
Gwen::Color result = HSVToColor(m_Hue, xPercent, yPercent);
result.a = 255;
return result;
}
void ColorLerpBox::Render(Gwen::Skin::Base* skin)
{
//Is there any way to move this into skin? Not for now, no idea how we'll "actually" render these
BaseClass::Render(skin);
for (int x = 0; x < Width(); x++)
{
for (int y = 0; y < Height(); y++)
{
skin->GetRender()->SetDrawColor(GetColorAtPos(x, y));
skin->GetRender()->DrawPixel(x, y);
}
}
skin->GetRender()->SetDrawColor(Gwen::Color(0, 0, 0, 255));
skin->GetRender()->DrawLinedRect(GetRenderBounds());
Gwen::Color selected = GetSelectedColor();
if ((selected.r + selected.g + selected.b) / 3 < 170)
skin->GetRender()->SetDrawColor(Gwen::Color(255, 255, 255, 255));
else
skin->GetRender()->SetDrawColor(Gwen::Color(0, 0, 0, 255));
Gwen::Rect testRect = Gwen::Rect(cursorPos.x - 3, cursorPos.y - 3, 6, 6);
skin->GetRender()->DrawShavedCornerRect(testRect);
}
GWEN_CONTROL_CONSTRUCTOR(ColorSlider)
{
SetSize(32, 128);
SetMouseInputEnabled(true);
m_bDepressed = false;
}
void ColorSlider::Render(Gwen::Skin::Base* skin)
{
//Is there any way to move this into skin? Not for now, no idea how we'll "actually" render these
int y = 0;
for (y = 0; y < Height(); y++)
{
float yPercent = (float)y / (float)Height();
skin->GetRender()->SetDrawColor(HSVToColor(yPercent * 360, 1, 1));
skin->GetRender()->DrawFilledRect(Gwen::Rect(5, y, Width() - 10, 1));
}
int drawHeight = m_iSelectedDist - 3;
//Draw our selectors
skin->GetRender()->SetDrawColor(Gwen::Color(0, 0, 0, 255));
skin->GetRender()->DrawFilledRect(Gwen::Rect(0, drawHeight + 2, Width(), 1));
skin->GetRender()->DrawFilledRect(Gwen::Rect(0, drawHeight, 5, 5));
skin->GetRender()->DrawFilledRect(Gwen::Rect(Width() - 5, drawHeight, 5, 5));
skin->GetRender()->SetDrawColor(Gwen::Color(255, 255, 255, 255));
skin->GetRender()->DrawFilledRect(Gwen::Rect(1, drawHeight + 1, 3, 3));
skin->GetRender()->DrawFilledRect(Gwen::Rect(Width() - 4, drawHeight + 1, 3, 3));
}
void ColorSlider::OnMouseClickLeft(int x, int y, bool bDown)
{
m_bDepressed = bDown;
if (bDown)
Gwen::MouseFocus = this;
else
Gwen::MouseFocus = NULL;
OnMouseMoved(x, y, 0, 0);
}
Gwen::Color ColorSlider::GetColorAtHeight(int y)
{
float yPercent = (float)y / (float)Height();
return HSVToColor(yPercent * 360, 1, 1);
}
void ColorSlider::OnMouseMoved(int x, int y, int /*deltaX*/, int /*deltaY*/)
{
if (m_bDepressed)
{
Gwen::Point cursorPos = CanvasPosToLocal(Gwen::Point(x, y));
if (cursorPos.y < 0)
cursorPos.y = 0;
if (cursorPos.y > Height())
cursorPos.y = Height();
m_iSelectedDist = cursorPos.y;
onSelectionChanged.Call(this);
}
}
void ColorSlider::SetColor(Gwen::Color color)
{
HSV hsv = RGBtoHSV(color.r, color.g, color.b);
m_iSelectedDist = hsv.h / 360 * Height();
onSelectionChanged.Call(this);
}
Gwen::Color ColorSlider::GetSelectedColor()
{
return GetColorAtHeight(m_iSelectedDist);
}

View file

@ -0,0 +1,58 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_COLORCONTROLS_H
#define GWEN_CONTROLS_COLORCONTROLS_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT ColorLerpBox : public Controls::Base
{
public:
GWEN_CONTROL(ColorLerpBox, Controls::Base);
virtual void Render(Gwen::Skin::Base* skin);
Gwen::Color GetColorAtPos(int x, int y);
void SetColor(Gwen::Color color, bool onlyHue = true);
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);
virtual void OnMouseClickLeft(int x, int y, bool bDown);
Gwen::Color GetSelectedColor();
Event::Caller onSelectionChanged;
protected:
Gwen::Point cursorPos;
bool m_bDepressed;
int m_Hue;
};
class GWEN_EXPORT ColorSlider : public Controls::Base
{
public:
GWEN_CONTROL(ColorSlider, Controls::Base);
virtual void Render(Gwen::Skin::Base* skin);
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);
virtual void OnMouseClickLeft(int x, int y, bool bDown);
Gwen::Color GetSelectedColor();
Gwen::Color GetColorAtHeight(int y);
void SetColor(Gwen::Color color);
Event::Caller onSelectionChanged;
protected:
int m_iSelectedDist;
bool m_bDepressed;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,217 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ColorPicker.h"
#include "Gwen/Controls/HorizontalSlider.h"
#include "Gwen/Controls/GroupBox.h"
#include "Gwen/Controls/TextBox.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(ColorPicker)
{
SetMouseInputEnabled(true);
SetKeyboardInputEnabled(true);
SetSize(256, 150);
CreateControls();
SetColor(Gwen::Color(50, 60, 70, 255));
}
void ColorPicker::CreateColorControl(Gwen::String name, int y)
{
int colorSize = 12;
GroupBox* colorGroup = new GroupBox(this);
colorGroup->SetPos(10, y);
colorGroup->SetText(name);
colorGroup->SetSize(160, 35);
colorGroup->SetName(name + "groupbox");
ColorDisplay* disp = new ColorDisplay(colorGroup);
disp->SetName(name);
disp->SetBounds(0, 10, colorSize, colorSize);
TextBoxNumeric* numeric = new TextBoxNumeric(colorGroup);
numeric->SetName(name + "Box");
numeric->SetPos(105, 7);
numeric->SetSize(26, 16);
numeric->SetSelectAllOnFocus(true);
numeric->onTextChanged.Add(this, &ColorPicker::NumericTyped);
HorizontalSlider* slider = new HorizontalSlider(colorGroup);
slider->SetPos(colorSize + 5, 10);
slider->SetRange(0, 255);
slider->SetSize(80, colorSize);
slider->SetName(name + "Slider");
slider->onValueChanged.Add(this, &ColorPicker::SlidersMoved);
}
void ColorPicker::NumericTyped(Gwen::Controls::Base* control)
{
if (!control)
return;
TextBoxNumeric* box = control->DynamicCastTextBoxNumeric();
if (!box)
return;
if (box->GetText() == L"")
return;
int textValue = atoi(Utility::UnicodeToString(box->GetText()).c_str());
if (textValue < 0) textValue = 0;
if (textValue > 255) textValue = 255;
if (box->GetName().find("Red") != Gwen::String::npos)
SetRed(textValue);
if (box->GetName().find("Green") != Gwen::String::npos)
SetGreen(textValue);
if (box->GetName().find("Blue") != Gwen::String::npos)
SetBlue(textValue);
if (box->GetName().find("Alpha") != Gwen::String::npos)
SetAlpha(textValue);
UpdateControls();
}
void ColorPicker::SetColor(Gwen::Color color)
{
m_Color = color;
UpdateControls();
}
void ColorPicker::CreateControls()
{
int startY = 5;
int height = 35;
CreateColorControl("Red", startY);
CreateColorControl("Green", startY + height);
CreateColorControl("Blue", startY + height * 2);
CreateColorControl("Alpha", startY + height * 3);
GroupBox* finalGroup = new GroupBox(this);
finalGroup->SetPos(180, 40);
finalGroup->SetSize(60, 60);
finalGroup->SetText("Result");
finalGroup->SetName("ResultGroupBox");
ColorDisplay* disp = new ColorDisplay(finalGroup);
disp->SetName("Result");
disp->SetBounds(0, 10, 32, 32);
disp->SetDrawCheckers(true);
//UpdateControls();
}
void ColorPicker::UpdateColorControls(Gwen::String name, Gwen::Color col, int sliderVal)
{
Base* el = FindChildByName(name, true);
ColorDisplay* disp = el ? el->DynamicCastColorDisplay() : 0;
disp->SetColor(col);
HorizontalSlider* slider = FindChildByName(name + "Slider", true)->DynamicCastHorizontalSlider();
slider->SetValue(sliderVal);
TextBoxNumeric* box = FindChildByName(name + "Box", true)->DynamicCastTextBoxNumeric();
box->SetText(Gwen::Utility::ToString(sliderVal));
}
void ColorPicker::UpdateControls()
{
//This is a little weird, but whatever for now
UpdateColorControls("Red", Color(GetColor().r, 0, 0, 255), GetColor().r);
UpdateColorControls("Green", Color(0, GetColor().g, 0, 255), GetColor().g);
UpdateColorControls("Blue", Color(0, 0, GetColor().b, 255), GetColor().b);
UpdateColorControls("Alpha", Color(255, 255, 255, GetColor().a), GetColor().a);
ColorDisplay* disp = FindChildByName("Result", true)->DynamicCastColorDisplay();
disp->SetColor(Color(GetColor().r, GetColor().g, GetColor().b, GetColor().a));
onColorChanged.Call(this);
}
void ColorPicker::SlidersMoved(Gwen::Controls::Base* control)
{
HorizontalSlider* slider = control->DynamicCastHorizontalSlider();
if (slider)
SetColorByName(GetColorFromName(slider->GetName()), slider->GetValue());
UpdateControls();
//SetColor( Gwen::Color( redSlider->GetValue(), greenSlider->GetValue(), blueSlider->GetValue(), alphaSlider->GetValue() ) );
}
void ColorPicker::Layout(Skin::Base* skin)
{
BaseClass::Layout(skin);
SizeToChildren(false, true);
SetSize(Width(), Height() + 5);
GroupBox* groupBox = FindChildByName("ResultGroupBox", true)->DynamicCastGroupBox();
if (groupBox)
groupBox->SetPos(groupBox->X(), Height() * 0.5f - groupBox->Height() * 0.5f);
UpdateControls();
}
void ColorPicker::Render(Skin::Base* skin)
{
skin->DrawBackground(this);
}
int ColorPicker::GetColorByName(Gwen::String colorName)
{
if (colorName == "Red")
return GetColor().r;
else if (colorName == "Green")
return GetColor().g;
else if (colorName == "Blue")
return GetColor().b;
else if (colorName == "Alpha")
return GetColor().a;
else
return 0;
}
Gwen::String ColorPicker::GetColorFromName(Gwen::String name)
{
if (name.find("Red") != Gwen::String::npos)
return "Red";
if (name.find("Green") != Gwen::String::npos)
return "Green";
if (name.find("Blue") != Gwen::String::npos)
return "Blue";
if (name.find("Alpha") != Gwen::String::npos)
return "Alpha";
else
return "";
}
void ColorPicker::SetColorByName(Gwen::String colorName, int colorValue)
{
if (colorName == "Red")
SetRed(colorValue);
else if (colorName == "Green")
SetGreen(colorValue);
else if (colorName == "Blue")
SetBlue(colorValue);
else if (colorName == "Alpha")
SetAlpha(colorValue);
}
void ColorPicker::SetAlphaVisible(bool visible)
{
GroupBox* groupBox = FindChildByName("Alphagroupbox", true)->DynamicCastGroupBox();
groupBox->SetHidden(!visible);
Invalidate();
}

View file

@ -0,0 +1,85 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_COLORPICKER_H
#define GWEN_CONTROLS_COLORPICKER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT ColorDisplay : public Controls::Base
{
public:
GWEN_CONTROL_INLINE(ColorDisplay, Controls::Base)
{
SetSize(32, 32);
m_Color = Color(255, 0, 0, 255);
m_DrawCheckers = true;
}
virtual void Render(Gwen::Skin::Base* skin)
{
skin->DrawColorDisplay(this, m_Color);
}
virtual void SetColor(Gwen::Color color) { m_Color = color; }
virtual Gwen::Color GetColor() { return m_Color; }
virtual void SetRed(int red) { m_Color.r = red; }
virtual void SetGreen(int green) { m_Color.g = green; }
virtual void SetBlue(int blue) { m_Color.b = blue; }
virtual void SetAlpha(int alpha) { m_Color.a = alpha; }
virtual void SetDrawCheckers(bool should) { m_DrawCheckers = should; }
protected:
Gwen::Color m_Color;
bool m_DrawCheckers;
};
} // namespace ControlsInternal
namespace Controls
{
class GWEN_EXPORT ColorPicker : public Base
{
public:
GWEN_CONTROL(ColorPicker, Base);
virtual void Render(Skin::Base* skin);
virtual void Layout(Skin::Base* skin);
virtual void CreateControls();
virtual void SlidersMoved(Gwen::Controls::Base* control);
virtual void NumericTyped(Gwen::Controls::Base* control);
virtual void UpdateControls();
virtual void UpdateColorControls(Gwen::String name, Gwen::Color col, int sliderVal);
virtual void CreateColorControl(Gwen::String name, int y);
virtual void SetColor(Gwen::Color color);
virtual Gwen::Color GetColor() { return m_Color; }
int GetColorByName(Gwen::String colorName);
void SetColorByName(Gwen::String colorName, int colorValue);
Gwen::String GetColorFromName(Gwen::String name);
virtual void SetAlphaVisible(bool visible);
virtual void SetRed(int red) { m_Color.r = red; }
virtual void SetGreen(int green) { m_Color.g = green; }
virtual void SetBlue(int blue) { m_Color.b = blue; }
virtual void SetAlpha(int alpha) { m_Color.a = alpha; }
Event::Caller onColorChanged;
protected:
Gwen::Color m_Color;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,197 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ComboBox.h"
#include "Gwen/Controls/Menu.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
class GWEN_EXPORT DownArrow : public Controls::Base
{
public:
GWEN_CONTROL_INLINE(DownArrow, Controls::Base)
{
SetMouseInputEnabled(true);
SetSize(15, 15);
}
void Render(Skin::Base* skin)
{
skin->DrawArrowDown(this->m_Bounds);
}
void SetComboBox(ComboBox* p) { m_ComboBox = p; }
protected:
ComboBox* m_ComboBox;
};
GWEN_CONTROL_CONSTRUCTOR(ComboBox)
{
SetSize(100, 20);
SetMouseInputEnabled(true);
m_Menu = new Menu(this);
m_Menu->SetHidden(true);
m_Menu->SetDisableIconMargin(true);
m_Menu->SetTabable(false);
ComboBoxButton* m_OpenButton = new ComboBoxButton(this);
m_OpenButton->onDown.Add(this, &ComboBox::OpenButtonPressed);
m_OpenButton->Dock(Pos::Right);
m_OpenButton->SetMargin(Margin(2, 2, 2, 2));
m_OpenButton->SetWidth(16);
m_OpenButton->SetTabable(false);
m_SelectedItem = NULL;
SetAlignment(Gwen::Pos::Left | Gwen::Pos::CenterV);
SetText(L"");
SetMargin(Margin(3, 0, 0, 0));
SetTabable(true);
}
MenuItem* ComboBox::AddItem(const UnicodeString& strLabel, const String& strName, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::Function fn)
{
MenuItem* pItem = m_Menu->AddItem(strLabel, L"", pHandler, fn);
pItem->SetName(strName);
pItem->onMenuItemSelected.Add(this, &ComboBox::OnItemSelected);
//Default
if (m_SelectedItem == NULL)
OnItemSelected(pItem);
return pItem;
}
void ComboBox::Render(Skin::Base* skin)
{
skin->DrawComboBox(this);
}
void ComboBox::OpenButtonPressed(Controls::Base* /*pControl*/)
{
OnPress();
}
void ComboBox::OnPress()
{
bool bWasMenuHidden = m_Menu->Hidden();
GetCanvas()->CloseMenus();
if (bWasMenuHidden)
{
OpenList();
}
else
{
m_Menu->SetHidden(true);
}
}
void ComboBox::ClearItems()
{
if (m_Menu)
{
m_Menu->ClearItems();
}
}
void ComboBox::OnItemSelected(Controls::Base* pControl)
{
//Convert selected to a menu item
MenuItem* pItem = pControl->DynamicCastMenuItem();
if (!pItem) return;
m_SelectedItem = pItem;
SetText(m_SelectedItem->GetText());
m_Menu->SetHidden(true);
onSelection.Call(this);
Focus();
Invalidate();
}
void ComboBox::OnLostKeyboardFocus()
{
SetTextColor(Color(0, 0, 0, 255));
}
void ComboBox::OnKeyboardFocus()
{
//Until we add the blue highlighting again
SetTextColor(Color(0, 0, 0, 255));
//m_SelectedText->SetTextColor( Color( 255, 255, 255, 255 ) );
}
Gwen::Controls::Label* ComboBox::GetSelectedItem()
{
return m_SelectedItem;
}
bool ComboBox::IsMenuOpen()
{
return m_Menu && !m_Menu->Hidden();
}
void ComboBox::OpenList()
{
if (!m_Menu) return;
m_Menu->SetParent(GetCanvas());
m_Menu->SetHidden(false);
m_Menu->BringToFront();
Gwen::Point p = LocalPosToCanvas(Gwen::Point(0, 0));
m_Menu->SetBounds(Gwen::Rect(p.x, p.y + Height(), Width(), m_Menu->Height()));
}
void ComboBox::CloseList()
{
}
bool ComboBox::OnKeyUp(bool bDown)
{
if (bDown)
{
Base::List& children = m_Menu->GetChildren();
Base::List::reverse_iterator it = std::find(children.rbegin(), children.rend(), m_SelectedItem);
if (it != children.rend() && (++it != children.rend()))
{
Base* pUpElement = *it;
OnItemSelected(pUpElement);
}
}
return true;
}
bool ComboBox::OnKeyDown(bool bDown)
{
if (bDown)
{
Base::List& children = m_Menu->GetChildren();
Base::List::iterator it = std::find(children.begin(), children.end(), m_SelectedItem);
if (it != children.end() && (++it != children.end()))
{
Base* pDownElement = *it;
OnItemSelected(pDownElement);
}
}
return true;
}
void ComboBox::RenderFocus(Gwen::Skin::Base* /*skin*/)
{
}

View file

@ -0,0 +1,83 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_COMBOBOX_H
#define GWEN_CONTROLS_COMBOBOX_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/TextBox.h"
#include "Gwen/Controls/Menu.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT ComboBoxButton : public Button
{
GWEN_CONTROL_INLINE(ComboBoxButton, Button) {}
virtual void Render(Skin::Base* skin)
{
skin->DrawComboBoxButton(this, m_bDepressed);
}
};
class GWEN_EXPORT ComboBox : public Button
{
public:
GWEN_CONTROL(ComboBox, Button);
virtual void Render(Skin::Base* skin);
virtual Gwen::Controls::Label* GetSelectedItem();
virtual void OnPress();
void OpenButtonPressed(Controls::Base* /*pControl*/);
virtual void OnItemSelected(Controls::Base* pControl);
virtual void OpenList();
virtual void CloseList();
virtual Controls::Base* GetControlAt(int x, int y)
{
if (x < 0 || y < 0 || x >= Width() || y >= Height())
return NULL;
return this;
}
virtual bool IsMenuComponent()
{
return true;
}
virtual void ClearItems();
virtual MenuItem* AddItem(const UnicodeString& strLabel, const String& strName = "", Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::Function fn = NULL);
virtual bool OnKeyUp(bool bDown);
virtual bool OnKeyDown(bool bDown);
virtual void RenderFocus(Gwen::Skin::Base* skin);
virtual void OnLostKeyboardFocus();
virtual void OnKeyboardFocus();
virtual bool IsMenuOpen();
Gwen::Event::Caller onSelection;
protected:
Menu* m_Menu;
MenuItem* m_SelectedItem;
Controls::Base* m_Button;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,181 @@
#include "Gwen/Gwen.h"
#include "Gwen/Controls/CrossSplitter.h"
#include "Gwen/Controls/Button.h"
using namespace Gwen;
using namespace Controls;
GWEN_CONTROL_CONSTRUCTOR(CrossSplitter)
{
m_VSplitter = new SplitterBar(this);
m_VSplitter->SetPos(0, 128);
m_VSplitter->onDragged.Add(this, &CrossSplitter::OnVerticalMoved);
m_VSplitter->SetCursor(Gwen::CursorType::SizeNS);
m_HSplitter = new SplitterBar(this);
m_HSplitter->SetPos(128, 0);
m_HSplitter->onDragged.Add(this, &CrossSplitter::OnHorizontalMoved);
m_HSplitter->SetCursor(Gwen::CursorType::SizeWE);
m_CSplitter = new SplitterBar(this);
m_CSplitter->SetPos(128, 128);
m_CSplitter->onDragged.Add(this, &CrossSplitter::OnCenterMoved);
m_CSplitter->SetCursor(Gwen::CursorType::SizeAll);
m_fHVal = 0.5f;
m_fVVal = 0.5f;
SetPanel(0, NULL);
SetPanel(1, NULL);
SetPanel(2, NULL);
SetPanel(3, NULL);
SetSplitterSize(5);
SetSplittersVisible(false);
m_iZoomedSection = -1;
}
void CrossSplitter::UpdateVSplitter()
{
m_VSplitter->MoveTo(m_VSplitter->X(), (Height() - m_VSplitter->Height()) * (m_fVVal));
}
void CrossSplitter::UpdateHSplitter()
{
m_HSplitter->MoveTo((Width() - m_HSplitter->Width()) * (m_fHVal), m_HSplitter->Y());
}
void CrossSplitter::OnCenterMoved(Controls::Base* /*control*/)
{
//Move the other two bars into position
CalculateValueCenter();
Invalidate();
}
void CrossSplitter::UpdateCSplitter()
{
m_CSplitter->MoveTo((Width() - m_CSplitter->Width()) * (m_fHVal), (Height() - m_CSplitter->Height()) * (m_fVVal));
}
void CrossSplitter::OnHorizontalMoved(Controls::Base* /*control*/)
{
m_fHVal = CalculateValueHorizontal();
Invalidate();
}
void CrossSplitter::OnVerticalMoved(Controls::Base* /*control*/)
{
m_fVVal = CalculateValueVertical();
Invalidate();
}
void CrossSplitter::CalculateValueCenter()
{
m_fHVal = (float)m_CSplitter->X() / (float)(Width() - m_CSplitter->Width());
m_fVVal = (float)m_CSplitter->Y() / (float)(Height() - m_CSplitter->Height());
}
float CrossSplitter::CalculateValueHorizontal()
{
return (float)m_HSplitter->X() / (float)(Width() - m_HSplitter->Width());
}
float CrossSplitter::CalculateValueVertical()
{
return (float)m_VSplitter->Y() / (float)(Height() - m_VSplitter->Height());
}
void CrossSplitter::Layout(Skin::Base* /*skin*/)
{
m_VSplitter->SetSize(Width(), m_fBarSize);
m_HSplitter->SetSize(m_fBarSize, Height());
m_CSplitter->SetSize(m_fBarSize, m_fBarSize);
UpdateVSplitter();
UpdateHSplitter();
UpdateCSplitter();
if (m_iZoomedSection == -1)
{
if (m_Sections[0])
m_Sections[0]->SetBounds(0, 0, m_HSplitter->X(), m_VSplitter->Y());
if (m_Sections[1])
m_Sections[1]->SetBounds(m_HSplitter->X() + m_fBarSize, 0, Width() - (m_HSplitter->X() + m_fBarSize), m_VSplitter->Y());
if (m_Sections[2])
m_Sections[2]->SetBounds(0, m_VSplitter->Y() + m_fBarSize, m_HSplitter->X(), Height() - (m_VSplitter->Y() + m_fBarSize));
if (m_Sections[3])
m_Sections[3]->SetBounds(m_HSplitter->X() + m_fBarSize, m_VSplitter->Y() + m_fBarSize, Width() - (m_HSplitter->X() + m_fBarSize), Height() - (m_VSplitter->Y() + m_fBarSize));
}
else
{
//This should probably use Fill docking instead
m_Sections[(int)m_iZoomedSection]->SetBounds(0, 0, Width(), Height());
}
}
void CrossSplitter::SetPanel(int index, Controls::Base* pPanel)
{
Debug::AssertCheck(index >= 0 && index <= 3, "CrossSplitter::SetPanel out of range");
m_Sections[index] = pPanel;
if (pPanel)
{
pPanel->Dock(Pos::None);
pPanel->SetParent(this);
}
Invalidate();
}
Controls::Base* CrossSplitter::GetPanel(int i)
{
return m_Sections[i];
}
void CrossSplitter::ZoomChanged()
{
onZoomChange.Call(this);
if (m_iZoomedSection == -1)
{
onUnZoomed.Call(this);
}
else
{
onZoomed.Call(this);
}
}
void CrossSplitter::Zoom(int section)
{
UnZoom();
if (m_Sections[section])
{
for (int i = 0; i < 4; i++)
{
if (i != section && m_Sections[i])
m_Sections[i]->SetHidden(true);
}
m_iZoomedSection = section;
Invalidate();
}
ZoomChanged();
}
void CrossSplitter::UnZoom()
{
m_iZoomedSection = -1;
for (int i = 0; i < 4; i++)
{
if (m_Sections[i])
m_Sections[i]->SetHidden(false);
}
Invalidate();
ZoomChanged();
}

View file

@ -0,0 +1,71 @@
#pragma once
#ifndef GWEN_CONTROLS_CROSSSPLITTER_H
#define GWEN_CONTROLS_CROSSSPLITTER_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/SplitterBar.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT CrossSplitter : public Controls::Base
{
public:
GWEN_CONTROL(CrossSplitter, Controls::Base);
void Layout(Skin::Base* skin);
virtual float CalculateValueVertical();
virtual float CalculateValueHorizontal();
virtual void CalculateValueCenter();
virtual void UpdateHSplitter();
virtual void UpdateVSplitter();
virtual void UpdateCSplitter();
virtual void OnVerticalMoved(Controls::Base* control);
virtual void OnHorizontalMoved(Controls::Base* control);
virtual void OnCenterMoved(Controls::Base* control);
virtual void SetPanel(int i, Controls::Base* pPanel);
virtual Controls::Base* GetPanel(int i);
virtual bool IsZoomed() { return m_iZoomedSection != -1; }
virtual void Zoom(int section);
virtual void UnZoom();
virtual void ZoomChanged();
virtual void CenterPanels()
{
m_fHVal = 0.5f;
m_fVVal = 0.5f;
Invalidate();
}
virtual void SetSplittersVisible(bool b)
{
m_VSplitter->SetShouldDrawBackground(b);
m_HSplitter->SetShouldDrawBackground(b);
m_CSplitter->SetShouldDrawBackground(b);
}
virtual void SetSplitterSize(int size) { m_fBarSize = size; }
private:
SplitterBar* m_VSplitter;
SplitterBar* m_HSplitter;
SplitterBar* m_CSplitter;
Controls::Base* m_Sections[4];
float m_fHVal;
float m_fVVal;
int m_fBarSize;
int m_iZoomedSection;
Gwen::Event::Caller onZoomed;
Gwen::Event::Caller onUnZoomed;
Gwen::Event::Caller onZoomChange;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,24 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Platform.h"
#include "Gwen/Controls/Dialogs/FileOpen.h"
using namespace Gwen;
using namespace Gwen::Dialogs;
void Gwen::Dialogs::FileOpenEx(bool bUseSystem, const String& Name, const String& StartPath, const String& Extension, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::FunctionStr fnCallback)
{
if (bUseSystem && Gwen::Platform::FileOpen(Name, StartPath, Extension, pHandler, fnCallback))
{
return;
}
//
// TODO: SHOW GWEN FILE SELECTION DIALOG
//
}

View file

@ -0,0 +1,24 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Platform.h"
#include "Gwen/Controls/Dialogs/FileSave.h"
using namespace Gwen;
using namespace Gwen::Dialogs;
void Gwen::Dialogs::FileSaveEx(bool bUseSystem, const String& Name, const String& StartPath, const String& Extension, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::FunctionStr fnCallback)
{
if (bUseSystem && Gwen::Platform::FileSave(Name, StartPath, Extension, pHandler, fnCallback))
{
return;
}
//
// TODO: SHOW GWEN FILE SELECTION DIALOG
//
}

View file

@ -0,0 +1,11 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Dialogs/Query.h"
using namespace Gwen;
using namespace Gwen::Controls;

View file

@ -0,0 +1,34 @@
#pragma once
#ifndef GWEN_CONTROLS_DIALOGS_FILEOPEN_H
#define GWEN_CONTROLS_DIALOGS_FILEOPEN_H
#include "Gwen/Gwen.h"
namespace Gwen
{
namespace Dialogs
{
// Usage:
//
// Gwen::Dialogs::FileOpen( true, "Open Map", "C:\my\folder\", "My Map Format|*.bmf", this, &MyClass::OpenFilename );
//
//
// The REAL function.
// If bUseSystem is used, it may use the system's modal dialog - which
// will steal focus and pause the rest of GWEN until it's continued.
//
void GWEN_EXPORT FileOpenEx(bool bUseSystem, const String& Name, const String& StartPath, const String& Extension, Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::FunctionStr fnCallback = NULL);
//
// Templated function simply to avoid having to manually cast the callback function.
//
template <typename A>
void FileOpen(bool bUseSystem, const String& Name, const String& StartPath, const String& Extension, Gwen::Event::Handler* pHandler = NULL, A fnCallback = NULL)
{
FileOpenEx(bUseSystem, Name, StartPath, Extension, pHandler, (Gwen::Event::Handler::FunctionStr)fnCallback);
}
} // namespace Dialogs
} // namespace Gwen
#endif

View file

@ -0,0 +1,39 @@
#pragma once
#ifndef GWEN_CONTROLS_DIALOGS_FILESAVE_H
#define GWEN_CONTROLS_DIALOGS_FILESAVE_H
#include "Gwen/Gwen.h"
namespace Gwen
{
namespace Dialogs
{
// Usage:
//
// Gwen::Dialogs::FileOpen( true, "Open Map", "C:\my\folder\", "My Map Format|*.bmf", this, &MyClass::OpenFilename );
//
//
// Callback function, for success
//
typedef void (Event::Handler::*FileSaveSuccessCallback)(const String& filename);
//
// The REAL function.
// If bUseSystem is used, it may use the system's modal dialog - which
// will steal focus and pause the rest of GWEN until it's continued.
//
void GWEN_EXPORT FileSaveEx(bool bUseSystem, const String& Name, const String& StartPath, const String& Extension, Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::FunctionStr fnCallback = NULL);
//
// Templated function simply to avoid having to manually cast the callback function.
//
template <typename A>
void FileSave(bool bUseSystem, const String& Name, const String& StartPath, const String& Extension, Gwen::Event::Handler* pHandler = NULL, A fnCallback = NULL)
{
FileSaveEx(bUseSystem, Name, StartPath, Extension, pHandler, (Gwen::Event::Handler::FunctionStr)fnCallback);
}
} // namespace Dialogs
} // namespace Gwen
#endif

View file

@ -0,0 +1,14 @@
#pragma once
#ifndef GWEN_CONTROLS_DIALOGS_QUERY_H
#define GWEN_CONTROLS_DIALOGS_QUERY_H
#include "Gwen/Gwen.h"
namespace Gwen
{
namespace Dialogs
{
//TODO. YesNo, Ok etc
}
} // namespace Gwen
#endif

View file

@ -0,0 +1,343 @@
/*
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);
}

View file

@ -0,0 +1,74 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_DOCKBASE_H
#define GWEN_CONTROLS_DOCKBASE_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
namespace Gwen
{
namespace Controls
{
class DockedTabControl;
class TabControl;
class GWEN_EXPORT DockBase : public Base
{
public:
GWEN_CONTROL(DockBase, Base);
virtual void Render(Skin::Base* skin);
virtual void RenderOver(Skin::Base* skin);
virtual bool IsEmpty();
virtual TabControl* GetTabControl();
virtual DockBase* GetRight() { return GetChildDock(Pos::Right); }
virtual DockBase* GetLeft() { return GetChildDock(Pos::Left); }
virtual DockBase* GetTop() { return GetChildDock(Pos::Top); }
virtual DockBase* GetBottom() { return GetChildDock(Pos::Bottom); }
// No action on space (default button action is to press)
virtual bool OnKeySpace(bool /*bDown*/) { return false; }
private:
// Drag n Drop
virtual bool DragAndDrop_HandleDrop(Gwen::DragAndDrop::Package* pPackage, int x, int y);
virtual bool DragAndDrop_CanAcceptPackage(Gwen::DragAndDrop::Package* pPackage);
virtual void DragAndDrop_HoverEnter(Gwen::DragAndDrop::Package* pPackage, int x, int y);
virtual void DragAndDrop_HoverLeave(Gwen::DragAndDrop::Package* pPackage);
virtual void DragAndDrop_Hover(Gwen::DragAndDrop::Package* pPackage, int x, int y);
virtual void SetupChildDock(int iPos);
virtual void DoRedundancyCheck();
virtual void DoConsolidateCheck();
virtual void OnRedundantChildDock(DockBase* pDockBase);
virtual int GetDroppedTabDirection(int x, int y);
virtual void OnTabRemoved(Gwen::Controls::Base* pControl);
DockBase* GetChildDock(int iPos);
DockBase** GetChildDockPtr(int iPos);
DockBase* m_Left;
DockBase* m_Right;
DockBase* m_Top;
DockBase* m_Bottom;
// Only CHILD dockpanels have a tabcontrol.
DockedTabControl* m_DockedTabControl;
bool m_bDrawHover;
bool m_bDropFar;
Gwen::Rect m_HoverRect;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,90 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/DockedTabControl.h"
#include "Gwen/Controls/Highlight.h"
#include "Gwen/DragAndDrop.h"
#include "Gwen/Controls/WindowControl.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(DockedTabControl)
{
m_WindowControl = NULL;
Dock(Pos::Fill);
m_pTitleBar = new TabTitleBar(this);
m_pTitleBar->Dock(Pos::Top);
m_pTitleBar->SetHidden(true);
}
void DockedTabControl::Layout(Skin::Base* skin)
{
GetTabStrip()->SetHidden(TabCount() <= 1);
UpdateTitleBar();
BaseClass::Layout(skin);
}
void DockedTabControl::UpdateTitleBar()
{
if (!GetCurrentButton()) return;
m_pTitleBar->UpdateFromTab(GetCurrentButton());
}
void DockedTabControl::DragAndDrop_StartDragging(Gwen::DragAndDrop::Package* pPackage, int x, int y)
{
BaseClass::DragAndDrop_StartDragging(pPackage, x, y);
SetHidden(true);
// This hiding our parent thing is kind of lousy.
GetParent()->SetHidden(true);
}
void DockedTabControl::DragAndDrop_EndDragging(bool bSuccess, int /*x*/, int /*y*/)
{
SetHidden(false);
if (!bSuccess)
{
GetParent()->SetHidden(false);
}
/*
if ( !bSuccess )
{
// Create our window control
if ( !m_WindowControl )
{
m_WindowControl = new WindowControl( GetCanvas() );
m_WindowControl->SetBounds( x, y, Width(), Height() );
}
m_WindowControl->SetPosition( x, y );
SetParent( m_WindowControl );
SetPosition( 0, 0 );
Dock( Pos::Fill );
}
*/
}
void DockedTabControl::MoveTabsTo(DockedTabControl* pTarget)
{
Base::List Children = GetTabStrip()->Children;
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
TabButton* pButton = (*iter)->DynamicCastTabButton();
if (!pButton) continue;
pTarget->AddPage(pButton);
}
Invalidate();
}

View file

@ -0,0 +1,39 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_DOCKEDTABCONTROL_H
#define GWEN_CONTROLS_DOCKEDTABCONTROL_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/TabControl.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT DockedTabControl : public TabControl
{
public:
GWEN_CONTROL(DockedTabControl, TabControl);
void SetShowTitlebar(bool bShow) { m_pTitleBar->SetHidden(!bShow); }
void Layout(Skin::Base* skin);
void UpdateTitleBar();
virtual void DragAndDrop_StartDragging(Gwen::DragAndDrop::Package* pPackage, int x, int y);
virtual void DragAndDrop_EndDragging(bool bSuccess, int x, int y);
void MoveTabsTo(DockedTabControl* pTarget);
private:
TabTitleBar* m_pTitleBar;
Base* m_WindowControl;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,56 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/Dragger.h"
using namespace Gwen;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(Dragger)
{
m_pTarget = NULL;
SetMouseInputEnabled(true);
m_bDepressed = false;
}
void Dragger::OnMouseClickLeft(int x, int y, bool bDown)
{
if (!m_pTarget) return;
if (bDown)
{
m_bDepressed = true;
m_HoldPos = m_pTarget->CanvasPosToLocal(Gwen::Point(x, y));
Gwen::MouseFocus = this;
}
else
{
m_bDepressed = false;
Gwen::MouseFocus = NULL;
}
}
void Dragger::OnMouseMoved(int x, int y, int /*deltaX*/, int /*deltaY*/)
{
if (!m_pTarget) return;
if (!m_bDepressed) return;
Gwen::Point p = Gwen::Point(x - m_HoldPos.x, y - m_HoldPos.y);
// Translate to parent
if (m_pTarget->GetParent())
p = m_pTarget->GetParent()->CanvasPosToLocal(p);
//m_pTarget->SetPosition( p.x, p.y );
m_pTarget->MoveTo(p.x, p.y);
onDragged.Call(this);
}
void Dragger::Render(Skin::Base* /*skin*/)
{
//skin->DrawButton(this,false,false);
}

View file

@ -0,0 +1,40 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_DRAGGER_H
#define GWEN_CONTROLS_DRAGGER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT Dragger : public Controls::Base
{
public:
GWEN_CONTROL(Dragger, Controls::Base);
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);
virtual void OnMouseClickLeft(int x, int y, bool bDown);
virtual void Render(Skin::Base* skin);
virtual void SetTarget(Controls::Base* pBase) { m_pTarget = pBase; }
Gwen::Event::Caller onDragged;
protected:
bool m_bDepressed;
Gwen::Point m_HoldPos;
Controls::Base* m_pTarget;
};
} // namespace ControlsInternal
} // namespace Gwen
#endif

View file

@ -0,0 +1,38 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/GroupBox.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(GroupBox)
{
// Set to true, because it's likely that our
// children will want mouse input, and they
// can't get it without us..
SetMouseInputEnabled(true);
SetTextPadding(Padding(10, 0, 0, 0));
SetAlignment(Pos::Top | Pos::Left);
Invalidate();
m_InnerPanel = new Base(this);
m_InnerPanel->Dock(Pos::Fill);
}
void GroupBox::Layout(Skin::Base* skin)
{
m_InnerPanel->SetMargin(Margin(TextHeight() + 3, 6, 6, 6));
BaseClass::Layout(skin);
}
void GroupBox::Render(Skin::Base* skin)
{
skin->DrawGroupBox(this, TextX(), TextHeight(), TextWidth());
}

View file

@ -0,0 +1,30 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_GROUPBOX_H
#define GWEN_CONTROLS_GROUPBOX_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT GroupBox : public Label
{
public:
GWEN_CONTROL(GroupBox, Label);
virtual void Render(Skin::Base* skin);
virtual void Layout(Skin::Base* skin);
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,164 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/HSVColorPicker.h"
#include "Gwen/Controls/ColorControls.h"
#include "Gwen/Controls/ColorPicker.h"
#include "Gwen/Controls/TextBox.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Controls/PanelListPanel.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(HSVColorPicker)
{
SetMouseInputEnabled(true);
SetSize(256, 128);
SetCacheToTexture();
m_LerpBox = new Gwen::Controls::ColorLerpBox(this);
m_LerpBox->onSelectionChanged.Add(this, &HSVColorPicker::ColorBoxChanged);
m_LerpBox->SetPos(5, 5);
m_ColorSlider = new Gwen::Controls::ColorSlider(this);
m_ColorSlider->SetPos(m_LerpBox->Width() + 15, 5);
m_ColorSlider->onSelectionChanged.Add(this, &HSVColorPicker::ColorSliderChanged);
m_After = new Gwen::ControlsInternal::ColorDisplay(this);
m_After->SetSize(48, 24);
m_After->SetPos(m_ColorSlider->X() + m_ColorSlider->Width() + 15, 5);
m_Before = new Gwen::ControlsInternal::ColorDisplay(this);
m_Before->SetSize(48, 24);
m_Before->SetPos(m_After->X(), 28);
int x = m_Before->X();
int y = m_Before->Y() + 30;
{
Label* label = new Label(this);
label->SetText(L"R:");
label->SizeToContents();
label->SetPos(x, y);
TextBoxNumeric* numeric = new TextBoxNumeric(this);
numeric->SetName("RedBox");
numeric->SetPos(x + 15, y - 1);
numeric->SetSize(26, 16);
numeric->SetSelectAllOnFocus(true);
numeric->onTextChanged.Add(this, &HSVColorPicker::NumericTyped);
}
y += 20;
{
Label* label = new Label(this);
label->SetText(L"G:");
label->SizeToContents();
label->SetPos(x, y);
TextBoxNumeric* numeric = new TextBoxNumeric(this);
numeric->SetName("GreenBox");
numeric->SetPos(x + 15, y - 1);
numeric->SetSize(26, 16);
numeric->SetSelectAllOnFocus(true);
numeric->onTextChanged.Add(this, &HSVColorPicker::NumericTyped);
}
y += 20;
{
Label* label = new Label(this);
label->SetText(L"B:");
label->SizeToContents();
label->SetPos(x, y);
TextBoxNumeric* numeric = new TextBoxNumeric(this);
numeric->SetName("BlueBox");
numeric->SetPos(x + 15, y - 1);
numeric->SetSize(26, 16);
numeric->SetSelectAllOnFocus(true);
numeric->onTextChanged.Add(this, &HSVColorPicker::NumericTyped);
}
}
void HSVColorPicker::NumericTyped(Gwen::Controls::Base* control)
{
TextBoxNumeric* box = control->DynamicCastTextBoxNumeric();
if (!box) return;
if (box->GetText() == L"") return;
int textValue = atoi(Gwen::Utility::UnicodeToString(box->GetText()).c_str());
if (textValue < 0) textValue = 0;
if (textValue > 255) textValue = 255;
Gwen::Color newColor = GetColor();
if (box->GetName().find("Red") != Gwen::String::npos)
{
newColor.r = textValue;
}
else if (box->GetName().find("Green") != Gwen::String::npos)
{
newColor.g = textValue;
}
else if (box->GetName().find("Blue") != Gwen::String::npos)
{
newColor.b = textValue;
}
else if (box->GetName().find("Alpha") != Gwen::String::npos)
{
newColor.a = textValue;
}
SetColor(newColor);
}
void HSVColorPicker::UpdateControls(Gwen::Color color)
{
TextBoxNumeric* redBox = FindChildByName("RedBox", false)->DynamicCastTextBoxNumeric();
if (redBox) redBox->SetText(Gwen::Utility::ToString((int)color.r), false);
TextBoxNumeric* greenBox = FindChildByName("GreenBox", false)->DynamicCastTextBoxNumeric();
if (greenBox) greenBox->SetText(Gwen::Utility::ToString((int)color.g), false);
TextBoxNumeric* blueBox = FindChildByName("BlueBox", false)->DynamicCastTextBoxNumeric();
if (blueBox) blueBox->SetText(Gwen::Utility::ToString((int)color.b), false);
m_After->SetColor(color);
}
void HSVColorPicker::SetColor(Gwen::Color color, bool onlyHue, bool reset)
{
UpdateControls(color);
if (reset)
m_Before->SetColor(color);
m_ColorSlider->SetColor(color);
m_LerpBox->SetColor(color, onlyHue);
m_After->SetColor(color);
}
Gwen::Color HSVColorPicker::GetColor()
{
return m_LerpBox->GetSelectedColor();
}
void HSVColorPicker::ColorBoxChanged(Gwen::Controls::Base* /*pControl*/)
{
onColorChanged.Call(this);
UpdateControls(GetColor());
Invalidate();
}
void HSVColorPicker::ColorSliderChanged(Gwen::Controls::Base* /*pControl*/)
{
if (m_LerpBox)
m_LerpBox->SetColor(m_ColorSlider->GetSelectedColor(), true);
Invalidate();
}

View file

@ -0,0 +1,46 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_HSVCOLORPICKER_H
#define GWEN_CONTROLS_HSVCOLORPICKER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/ColorControls.h"
#include "Gwen/Controls/ColorPicker.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT HSVColorPicker : public Controls::Base
{
public:
GWEN_CONTROL(HSVColorPicker, Controls::Base);
Gwen::Color GetColor();
Gwen::Color GetDefaultColor() { return m_Before->GetColor(); }
void SetColor(Gwen::Color color, bool onlyHue = false, bool reset = false);
void ColorBoxChanged(Gwen::Controls::Base* pControl);
void ColorSliderChanged(Gwen::Controls::Base* pControl);
void NumericTyped(Gwen::Controls::Base* control);
void UpdateControls(Gwen::Color newColor);
Event::Caller onColorChanged;
protected:
ColorLerpBox* m_LerpBox;
ColorSlider* m_ColorSlider;
ControlsInternal::ColorDisplay* m_Before;
ControlsInternal::ColorDisplay* m_After;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,34 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_HIGHLIGHT_H
#define GWEN_CONTROLS_HIGHLIGHT_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT Highlight : public Controls::Base
{
public:
GWEN_CONTROL_INLINE(Highlight, Controls::Base)
{
}
void Render(Skin::Base* skin)
{
skin->DrawHighlight(this);
}
};
} // namespace ControlsInternal
} // namespace Gwen
#endif

View file

@ -0,0 +1,133 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ScrollBar.h"
#include "Gwen/Controls/HorizontalScrollBar.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(HorizontalScrollBar)
{
m_Bar->SetHorizontal();
m_ScrollButton[SCROLL_BUTTON_LEFT]->SetDirectionLeft();
m_ScrollButton[SCROLL_BUTTON_LEFT]->onPress.Add(this, &HorizontalScrollBar::NudgeLeft);
m_ScrollButton[SCROLL_BUTTON_RIGHT]->SetDirectionRight();
m_ScrollButton[SCROLL_BUTTON_RIGHT]->onPress.Add(this, &HorizontalScrollBar::NudgeRight);
m_Bar->onDragged.Add(this, &HorizontalScrollBar::OnBarMoved);
}
void HorizontalScrollBar::Layout(Skin::Base* skin)
{
BaseClass::Layout(skin);
m_ScrollButton[SCROLL_BUTTON_LEFT]->SetWidth(Height());
m_ScrollButton[SCROLL_BUTTON_LEFT]->Dock(Pos::Left);
m_ScrollButton[SCROLL_BUTTON_RIGHT]->SetWidth(Height());
m_ScrollButton[SCROLL_BUTTON_RIGHT]->Dock(Pos::Right);
m_Bar->SetHeight(GetButtonSize());
m_Bar->SetPadding(Padding(GetButtonSize(), 0, GetButtonSize(), 0));
float barWidth = (m_fViewableContentSize / m_fContentSize) * (Width() - (GetButtonSize() * 2));
if (barWidth < GetButtonSize() * 0.5)
barWidth = GetButtonSize() * 0.5;
m_Bar->SetWidth(barWidth);
m_Bar->SetHidden(Width() - (GetButtonSize() * 2) <= barWidth);
//Based on our last scroll amount, produce a position for the bar
if (!m_Bar->IsDepressed())
{
SetScrolledAmount(GetScrolledAmount(), true);
}
}
void HorizontalScrollBar::NudgeLeft(Base* /*control*/)
{
if (!IsDisabled())
SetScrolledAmount(GetScrolledAmount() - GetNudgeAmount(), true);
}
void HorizontalScrollBar::NudgeRight(Base* /*control*/)
{
if (!IsDisabled())
SetScrolledAmount(GetScrolledAmount() + GetNudgeAmount(), true);
}
void HorizontalScrollBar::ScrollToLeft()
{
SetScrolledAmount(0, true);
}
void HorizontalScrollBar::ScrollToRight()
{
SetScrolledAmount(1, true);
}
float HorizontalScrollBar::GetNudgeAmount()
{
if (m_bDepressed)
return m_fViewableContentSize / m_fContentSize;
else
return BaseClass::GetNudgeAmount();
}
void HorizontalScrollBar::OnMouseClickLeft(int x, int y, bool bDown)
{
if (bDown)
{
m_bDepressed = true;
Gwen::MouseFocus = this;
}
else
{
Gwen::Point clickPos = CanvasPosToLocal(Gwen::Point(x, y));
if (clickPos.x < m_Bar->X())
NudgeLeft(this);
else if (clickPos.x > m_Bar->X() + m_Bar->Width())
NudgeRight(this);
m_bDepressed = false;
Gwen::MouseFocus = NULL;
}
}
float HorizontalScrollBar::CalculateScrolledAmount()
{
return (float)(m_Bar->X() - GetButtonSize()) / (float)(Width() - m_Bar->Width() - (GetButtonSize() * 2));
}
bool HorizontalScrollBar::SetScrolledAmount(float amount, bool forceUpdate)
{
amount = Gwen::Clamp(amount, 0, 1);
if (!BaseClass::SetScrolledAmount(amount, forceUpdate))
return false;
if (forceUpdate)
{
int newX = GetButtonSize() + (amount * ((Width() - m_Bar->Width()) - (GetButtonSize() * 2)));
m_Bar->MoveTo(newX, m_Bar->Y());
}
return true;
}
void HorizontalScrollBar::OnBarMoved(Controls::Base* control)
{
if (m_Bar->IsDepressed())
{
SetScrolledAmount(CalculateScrolledAmount(), false);
BaseClass::OnBarMoved(control);
}
else
InvalidateParent();
}

View file

@ -0,0 +1,48 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_HORIZONTALSCROLLBAR_H
#define GWEN_CONTROLS_HORIZONTALSCROLLBAR_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Dragger.h"
#include "Gwen/Controls/ScrollBar.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT HorizontalScrollBar : public BaseScrollBar
{
public:
GWEN_CONTROL(HorizontalScrollBar, BaseScrollBar);
virtual void Layout(Skin::Base* skin);
virtual void OnMouseClickLeft(int x, int y, bool bDown);
virtual void OnBarMoved(Controls::Base* control);
virtual int GetBarSize() { return m_Bar->Width(); }
virtual int GetBarPos() { return m_Bar->X() - Height(); }
virtual void SetBarSize(int size) { m_Bar->SetWidth(size); }
virtual int GetButtonSize() { return Height(); }
virtual void ScrollToLeft();
virtual void ScrollToRight();
virtual void NudgeLeft(Base* control);
virtual void NudgeRight(Base* control);
virtual float GetNudgeAmount();
virtual float CalculateScrolledAmount();
virtual bool SetScrolledAmount(float amount, bool forceUpdate);
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,43 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/Slider.h"
#include "Gwen/Controls/HorizontalSlider.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(HorizontalSlider)
{
}
float HorizontalSlider::CalculateValue()
{
return (float)m_SliderBar->X() / (float)(Width() - m_SliderBar->Width());
}
void HorizontalSlider::UpdateBarFromValue()
{
m_SliderBar->MoveTo((Width() - m_SliderBar->Width()) * (m_fValue), m_SliderBar->Y());
}
void HorizontalSlider::OnMouseClickLeft(int x, int y, bool bDown)
{
m_SliderBar->MoveTo(CanvasPosToLocal(Gwen::Point(x, y)).x - m_SliderBar->Width() * 0.5, m_SliderBar->Y());
m_SliderBar->OnMouseClickLeft(x, y, bDown);
OnMoved(m_SliderBar);
}
void HorizontalSlider::Layout(Skin::Base* /*skin*/)
{
m_SliderBar->SetSize(10, Height());
}
void HorizontalSlider::Render(Skin::Base* skin)
{
skin->DrawSlider(this, true, m_bClampToNotches ? m_iNumNotches : 0, m_SliderBar->Width());
}

View file

@ -0,0 +1,35 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_HORIZONTALSLIDER_H
#define GWEN_CONTROLS_HORIZONTALSLIDER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/Dragger.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Slider.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT HorizontalSlider : public Slider
{
GWEN_CONTROL(HorizontalSlider, Slider);
virtual void Layout(Skin::Base* skin);
virtual void Render(Skin::Base* skin);
virtual float CalculateValue();
virtual void UpdateBarFromValue();
virtual void OnMouseClickLeft(int x, int y, bool bDown);
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,7 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ImagePanel.h"

View file

@ -0,0 +1,75 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_IMAGEPANEL_H
#define GWEN_CONTROLS_IMAGEPANEL_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/BaseRender.h"
#include "Gwen/Texture.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT ImagePanel : public Controls::Base
{
public:
GWEN_CONTROL_INLINE(ImagePanel, Controls::Base)
{
SetUV(0, 0, 1, 1);
SetMouseInputEnabled(false);
m_DrawColor = Colors::White;
}
virtual ~ImagePanel()
{
m_Texture.Release(GetSkin()->GetRender());
}
virtual void SetUV(float u1, float v1, float u2, float v2)
{
m_uv[0] = u1;
m_uv[1] = v1;
m_uv[2] = u2;
m_uv[3] = v2;
}
virtual void SetImage(const TextObject& imageName)
{
m_Texture.Load(imageName, GetSkin()->GetRender());
}
virtual const TextObject& GetImageName()
{
return m_Texture.name;
}
virtual void Render(Skin::Base* skin)
{
skin->GetRender()->SetDrawColor(m_DrawColor);
skin->GetRender()->DrawTexturedRect(&m_Texture, GetRenderBounds(), m_uv[0], m_uv[1], m_uv[2], m_uv[3]);
}
virtual void SizeToContents()
{
SetSize(m_Texture.width, m_Texture.height);
}
virtual void SetDrawColor(Gwen::Color& color)
{
m_DrawColor = color;
}
Texture m_Texture;
float m_uv[4];
Gwen::Color m_DrawColor;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,71 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(Label)
{
m_Text = new ControlsInternal::Text(this);
m_Text->SetFont(GetSkin()->GetDefaultFont());
SetMouseInputEnabled(false);
SetBounds(0, 0, 100, 10);
SetAlignment(Gwen::Pos::Left | Gwen::Pos::Top);
}
void Label::Layout(Skin::Base* /*skin*/)
{
int iAlign = m_iAlign;
int x = m_rTextPadding.left + m_Padding.left;
int y = m_rTextPadding.top + m_Padding.top;
if (iAlign & Pos::Right) x = Width() - m_Text->Width() - m_rTextPadding.right - m_Padding.right;
if (iAlign & Pos::CenterH) x = (m_rTextPadding.left + m_Padding.left) + ((Width() - m_Text->Width()) * 0.5f) - m_rTextPadding.right - m_Padding.right;
if (iAlign & Pos::CenterV) y = (m_rTextPadding.top + m_Padding.top) + ((Height() - m_Text->Height()) * 0.5f) - m_rTextPadding.bottom - m_Padding.bottom;
if (iAlign & Pos::Bottom) y = Height() - m_Text->Height() - m_rTextPadding.bottom - m_Padding.bottom;
m_Text->SetPos(x, y);
}
void Label::SetText(const UnicodeString& str, bool bDoEvents)
{
if (m_Text->GetText() == str) return;
m_Text->SetString(str);
Redraw();
if (bDoEvents)
OnTextChanged();
}
void Label::SetText(const String& str, bool bDoEvents)
{
SetText(Gwen::Utility::StringToUnicode(str), bDoEvents);
}
void Label::SizeToContents()
{
m_Text->SetPos(m_rTextPadding.left + m_Padding.left, m_rTextPadding.top + m_Padding.top);
m_Text->RefreshSize();
SetSize(m_Text->Width() + m_Padding.left + m_Padding.right + m_rTextPadding.left + m_rTextPadding.right, m_Text->Height() + m_Padding.top + m_Padding.bottom + m_rTextPadding.top + m_rTextPadding.bottom);
}
Gwen::Point Label::GetCharacterPosition(int iChar)
{
Gwen::Point p = m_Text->GetCharacterPosition(iChar);
p.x += m_Text->X();
p.y += m_Text->Y();
return p;
}

View file

@ -0,0 +1,72 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_LABEL_H
#define GWEN_CONTROLS_LABEL_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Text.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT Label : public Controls::Base
{
public:
GWEN_CONTROL(Label, Controls::Base);
virtual void SetText(const UnicodeString& str, bool bDoEvents = true);
virtual void SetText(const String& str, bool bDoEvents = true);
virtual const UnicodeString& GetText() const { return m_Text->GetText(); }
virtual void Render(Skin::Base* /*skin*/) {}
virtual void Layout(Skin::Base* skin);
virtual void SizeToContents();
virtual void SetAlignment(int iAlign) { m_iAlign = iAlign; }
virtual void SetFont(Gwen::Font* pFont) { m_Text->SetFont(pFont); }
virtual Gwen::Font* GetFont() { return m_Text->GetFont(); }
virtual void SetTextColor(const Gwen::Color& col) { m_Text->SetTextColor(col); }
inline const Gwen::Color& TextColor() const { return m_Text->TextColor(); }
virtual int TextWidth() { return m_Text->Width(); }
virtual int TextRight() { return m_Text->Right(); }
virtual int TextHeight() { return m_Text->Height(); }
virtual int TextX() { return m_Text->X(); }
virtual int TextY() { return m_Text->Y(); }
virtual int TextLength() { return m_Text->Length(); }
Gwen::Point GetCharacterPosition(int iChar);
virtual void SetTextPadding(const Padding& padding)
{
m_rTextPadding = padding;
Invalidate();
InvalidateParent();
}
virtual const Padding& GetTextPadding() { return m_rTextPadding; }
virtual Gwen::UnicodeString GetText() { return m_Text->GetText(); }
inline int Alignment() const { return m_iAlign; }
protected:
virtual void OnTextChanged(){};
Padding m_rTextPadding;
ControlsInternal::Text* m_Text;
int m_iAlign;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,24 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/LabelClickable.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(LabelClickable)
{
SetIsToggle(false);
SetAlignment(Gwen::Pos::Left | Gwen::Pos::CenterV);
}
void LabelClickable::Render(Skin::Base* /*skin*/)
{
//skin->DrawButton( this, IsDepressed(), IsToggle() && GetToggleState() );
}

View file

@ -0,0 +1,27 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_LABELCLICKABLE_H
#define GWEN_CONTROLS_LABELCLICKABLE_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT LabelClickable : public Button
{
public:
GWEN_CONTROL(LabelClickable, Button);
virtual void Render(Skin::Base* skin);
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,82 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_LAYOUT_SPLITTER_H
#define GWEN_CONTROLS_LAYOUT_SPLITTER_H
#include "Gwen/Controls/Base.h"
namespace Gwen
{
namespace Controls
{
namespace Layout
{
class GWEN_EXPORT Splitter : public Base
{
public:
typedef Base BaseClass;
Splitter(Base* pParent) : BaseClass(pParent)
{
for (int i = 0; i < 2; i++)
m_pPanel[i] = NULL;
}
void SetPanel(int i, Base* pPanel)
{
if (i < 0 || i > 1) return;
m_pPanel[i] = pPanel;
if (m_pPanel[i])
{
m_pPanel[i]->SetParent(this);
}
}
Base* GetPanel(int i) const
{
if (i < 0 || i > 1) return NULL;
return m_pPanel[i];
}
void Layout(Skin::Base* skin)
{
LayoutVertical(skin);
}
private:
void LayoutVertical(Skin::Base* /*skin*/)
{
int w = Width();
int h = Height();
if (m_pPanel[0])
{
const Margin& m = m_pPanel[0]->GetMargin();
m_pPanel[0]->SetBounds(m.left, m.top, w - m.left - m.right, (h * 0.5) - m.top - m.bottom);
}
if (m_pPanel[1])
{
const Margin& m = m_pPanel[1]->GetMargin();
m_pPanel[1]->SetBounds(m.left, m.top + (h * 0.5f), w - m.left - m.right, (h * 0.5f) - m.top - m.bottom);
}
}
void LayoutHorizontal(Skin::Base* /*skin*/)
{
// Todo.
}
Base* m_pPanel[2];
};
} // namespace Layout
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,309 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_LAYOUT_TABLE_H
#define GWEN_CONTROLS_LAYOUT_TABLE_H
#include "Gwen/Controls/Label.h"
#include "Gwen/Utility.h"
namespace Gwen
{
namespace Controls
{
namespace Layout
{
class Table;
class GWEN_EXPORT TableRow : public Base
{
static const int MaxColumns = 5;
GWEN_CONTROL_INLINE(TableRow, Base)
{
for (int i = 0; i < MaxColumns; i++)
m_Columns[i] = NULL;
m_ColumnCount = 0;
}
virtual class TableRow* DynamicCastLayoutTableRow()
{
return this;
}
virtual const class TableRow* DynamicCastLayoutTableRow() const
{
return this;
}
void SetColumnCount(int iCount)
{
if (iCount == m_ColumnCount) return;
if (iCount >= MaxColumns)
m_ColumnCount = MaxColumns;
for (int i = 0; i < MaxColumns; i++)
{
if (i < iCount)
{
if (!m_Columns[i])
{
m_Columns[i] = new Label(this);
m_Columns[i]->Dock(Pos::Left);
m_Columns[i]->SetPadding(Padding(3, 3, 3, 3));
}
}
else if (m_Columns[i])
{
m_Columns[i]->DelayedDelete();
m_Columns[i] = NULL;
}
m_ColumnCount = iCount;
}
}
void SetColumnWidth(int i, int iWidth)
{
if (!m_Columns[i]) return;
if (m_Columns[i]->Width() == iWidth) return;
m_Columns[i]->SetWidth(iWidth);
}
template <typename T>
void SetCellText(int i, const T& strString)
{
if (!m_Columns[i]) return;
m_Columns[i]->SetText(strString);
}
void SetCellContents(int i, Base* pControl, bool bEnableMouseInput = false)
{
if (!m_Columns[i]) return;
pControl->SetParent(m_Columns[i]);
m_Columns[i]->SetMouseInputEnabled(bEnableMouseInput);
}
Label* GetCellContents(int i)
{
return m_Columns[i];
}
void SizeToContents()
{
int iHeight = 0;
for (int i = 0; i < m_ColumnCount; i++)
{
if (!m_Columns[i]) continue;
// Note, more than 1 child here, because the
// label has a child built in ( The Text )
if (m_Columns[i]->NumChildren() > 1)
{
m_Columns[i]->SizeToChildren();
}
else
{
m_Columns[i]->SizeToContents();
}
iHeight = Utility::Max(iHeight, m_Columns[i]->Height());
}
SetHeight(iHeight);
}
void SetTextColor(const Gwen::Color& color)
{
for (int i = 0; i < m_ColumnCount; i++)
{
if (!m_Columns[i]) continue;
m_Columns[i]->SetTextColor(color);
}
}
//You might hate this. Actually I know you will
virtual UnicodeString GetText(int i)
{
return m_Columns[i]->GetText();
}
virtual void SetSelected(bool /*b*/) {}
//
// This is sometimes called by derivatives.
//
Gwen::Event::Caller onRowSelected;
private:
int m_ColumnCount;
Label* m_Columns[MaxColumns];
friend class Table;
};
class GWEN_EXPORT Table : public Base
{
public:
GWEN_CONTROL_INLINE(Table, Base)
{
m_iColumnCount = 1;
m_iDefaultRowHeight = 22;
for (int i = 0; i < TableRow::MaxColumns; i++)
{
m_ColumnWidth[i] = 20;
}
m_bSizeToContents = false;
}
void SetColumnCount(int i)
{
if (m_iColumnCount == i) return;
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
if (!*it)
continue;
TableRow* pRow = (*it)->DynamicCastLayoutTableRow();
if (!pRow) continue;
pRow->SetColumnCount(i);
}
m_iColumnCount = i;
}
void SetColumnWidth(int i, int iWidth)
{
if (m_ColumnWidth[i] == iWidth) return;
m_ColumnWidth[i] = iWidth;
Invalidate();
}
TableRow* AddRow()
{
TableRow* row = new TableRow(this);
row->SetColumnCount(m_iColumnCount);
row->SetHeight(m_iDefaultRowHeight);
row->Dock(Pos::Top);
return row;
}
void AddRow(TableRow* pRow)
{
pRow->SetParent(this);
pRow->SetColumnCount(m_iColumnCount);
pRow->SetHeight(m_iDefaultRowHeight);
pRow->Dock(Pos::Top);
}
void Remove(TableRow* pRow)
{
pRow->DelayedDelete();
}
void Clear()
{
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
if (!(*it))
continue;
TableRow* pRow = (*it)->DynamicCastLayoutTableRow();
if (!pRow) continue;
Remove(pRow);
}
}
void Layout(Skin::Base* skin)
{
BaseClass::Layout(skin);
if (m_bSizeToContents)
{
DoSizeToContents();
}
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
if (!*it)
continue;
TableRow* pRow = (*it)->DynamicCastLayoutTableRow();
if (!pRow) continue;
for (int i = 0; i < TableRow::MaxColumns && i < m_iColumnCount; i++)
{
pRow->SetColumnWidth(i, m_ColumnWidth[i]);
}
}
}
void PostLayout(Skin::Base* /*skin*/)
{
if (m_bSizeToContents)
{
SizeToChildren();
m_bSizeToContents = false;
}
}
void SizeToContents()
{
m_bSizeToContents = true;
Invalidate();
}
void DoSizeToContents()
{
for (int i = 0; i < TableRow::MaxColumns; i++)
{
m_ColumnWidth[i] = 10;
}
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
if (!*it)
continue;
TableRow* pRow = (*it)->DynamicCastLayoutTableRow();
if (!pRow) continue;
pRow->SizeToContents();
for (int i = 0; i < TableRow::MaxColumns; i++)
{
if (pRow->m_Columns[i])
{
m_ColumnWidth[i] = Utility::Max(m_ColumnWidth[i], pRow->m_Columns[i]->Width());
}
}
//iBottom += pRow->Height();
}
InvalidateParent();
}
private:
bool m_bSizeToContents;
int m_iColumnCount;
int m_iDefaultRowHeight;
int m_ColumnWidth[TableRow::MaxColumns];
};
} // namespace Layout
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,140 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ListBox.h"
#include "Gwen/Controls/ScrollControl.h"
#include "Gwen/InputHandler.h"
using namespace Gwen;
using namespace Gwen::Controls;
class ListBoxRow : public Layout::TableRow
{
GWEN_CONTROL_INLINE(ListBoxRow, Layout::TableRow)
{
SetMouseInputEnabled(true);
SetSelected(false);
}
void Render(Skin::Base* skin)
{
skin->DrawListBoxLine(this, IsSelected());
}
bool IsSelected() const
{
return m_bSelected;
}
void OnMouseClickLeft(int /*x*/, int /*y*/, bool bDown)
{
if (bDown && !m_bSelected)
{
SetSelected(true);
onRowSelected.Call(this);
}
}
void SetSelected(bool b)
{
m_bSelected = b;
// TODO: Get these values from the skin.
if (b)
SetTextColor(Gwen::Colors::White);
else
SetTextColor(Gwen::Colors::Black);
}
private:
bool m_bSelected;
};
GWEN_CONTROL_CONSTRUCTOR(ListBox)
{
m_ScrollControl = new ScrollControl(this);
m_ScrollControl->Dock(Pos::Fill);
m_ScrollControl->SetScroll(false, true);
m_ScrollControl->SetAutoHideBars(true);
m_ScrollControl->SetMargin(Margin(1, 1, 1, 1));
m_InnerPanel = m_ScrollControl;
m_Table = new Controls::Layout::Table(this);
m_Table->Dock(Pos::Top);
m_Table->SetColumnCount(1);
m_bMultiSelect = false;
}
void ListBox::OnChildBoundsChanged(Gwen::Rect /*oldChildBounds*/, Base* /*pChild*/)
{
m_ScrollControl->UpdateScrollBars();
}
Layout::TableRow* ListBox::AddItem(const String& strLabel, const String& strName)
{
return AddItem(Utility::StringToUnicode(strLabel), strName);
}
Layout::TableRow* ListBox::AddItem(const UnicodeString& strLabel, const String& strName)
{
ListBoxRow* pRow = new ListBoxRow(this);
m_Table->AddRow(pRow);
pRow->SetCellText(0, strLabel);
pRow->SetName(strName);
pRow->onRowSelected.Add(this, &ListBox::OnRowSelected);
m_Table->SizeToContents();
return pRow;
}
void ListBox::Render(Skin::Base* skin)
{
skin->DrawListBox(this);
}
void ListBox::UnselectAll()
{
std::list<Layout::TableRow*>::iterator it = m_SelectedRows.begin();
while (it != m_SelectedRows.end())
{
ListBoxRow* pRow = static_cast<ListBoxRow*>(*it);
it = m_SelectedRows.erase(it);
pRow->SetSelected(false);
}
}
void ListBox::OnRowSelected(Base* pControl)
{
ListBoxRow* pRow = static_cast<ListBoxRow*>(pControl);
if (!AllowMultiSelect() || !Gwen::Input::IsShiftDown())
{
UnselectAll();
}
m_SelectedRows.push_back(pRow);
onRowSelected.Call(this);
}
Layout::TableRow* ListBox::GetSelectedRow()
{
if (m_SelectedRows.empty()) return NULL;
return *m_SelectedRows.begin();
}
void ListBox::Clear()
{
UnselectAll();
m_Table->Clear();
}

View file

@ -0,0 +1,63 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_LISTBOX_H
#define GWEN_CONTROLS_LISTBOX_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Layout/Table.h"
#include "Gwen/Controls/ScrollControl.h"
namespace Gwen
{
namespace Controls
{
class ScrollControl;
class GWEN_EXPORT ListBox : public Base
{
public:
GWEN_CONTROL(ListBox, Base);
typedef std::list<Layout::TableRow*> Rows;
Layout::TableRow* AddItem(const String& strLabel, const String& strName = "");
Layout::TableRow* AddItem(const UnicodeString& strLabel, const String& strName = "");
void Render(Skin::Base* skin);
void UnselectAll();
void SetColumnCount(int iCount) { m_Table->SetColumnCount(iCount); }
void SetAllowMultiSelect(bool bMultiSelect) { m_bMultiSelect = bMultiSelect; }
bool AllowMultiSelect() const { return m_bMultiSelect; }
const ListBox::Rows& GetSelectedRows() { return m_SelectedRows; }
Layout::TableRow* GetSelectedRow();
Gwen::Controls::ScrollControl* Scroller() { return m_ScrollControl; }
void OnChildBoundsChanged(Gwen::Rect oldChildBounds, Base* pChild);
Gwen::Event::Caller onRowSelected;
Controls::Layout::Table* GetTable() { return m_Table; }
virtual void Clear();
protected:
void OnRowSelected(Base* pControl);
Controls::Layout::Table* m_Table;
ListBox::Rows m_SelectedRows;
Controls::ScrollControl* m_ScrollControl;
bool m_bMultiSelect;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,166 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Menu.h"
#include "Gwen/Skin.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(Menu)
{
SetBounds(0, 0, 10, 10);
SetPadding(Padding(2, 2, 2, 2));
SetDisableIconMargin(false);
SetAutoHideBars(true);
SetScroll(false, true);
}
void Menu::Render(Skin::Base* skin)
{
skin->DrawMenu(this, IconMarginDisabled());
}
void Menu::RenderUnder(Skin::Base* skin)
{
BaseClass::RenderUnder(skin);
skin->DrawShadow(this);
}
void Menu::Layout(Skin::Base* skin)
{
int childrenHeight = 0;
for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
{
Base* pChild = (*it);
if (!pChild)
continue;
childrenHeight += pChild->Height();
}
if (Y() + childrenHeight > GetCanvas()->Height())
childrenHeight = GetCanvas()->Height() - Y();
SetSize(Width(), childrenHeight);
BaseClass::Layout(skin);
}
MenuItem* Menu::AddItem(const Gwen::UnicodeString& strName, const UnicodeString& strIconName, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::Function fn)
{
MenuItem* pItem = new MenuItem(this);
pItem->SetText(strName);
pItem->SetImage(strIconName);
if (fn && pHandler)
{
pItem->onMenuItemSelected.Add(pHandler, fn);
}
OnAddItem(pItem);
return pItem;
}
void Menu::OnAddItem(MenuItem* item)
{
item->Dock(Pos::Top);
item->SetTextPadding(Padding(IconMarginDisabled() ? 0 : 24, 0, 16, 0));
item->SetPadding(Padding(4, 4, 4, 4));
item->SizeToContents();
item->SetAlignment(Pos::CenterV | Pos::Left);
item->onHoverEnter.Add(this, &Menu::OnHoverItem);
// Do this here - after Top Docking these values mean nothing in layout
int w = item->Width() + 10 + 32;
if (w < Width()) w = Width();
SetSize(w, Height());
}
void Menu::ClearItems()
{
for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
{
Base* pChild = *it;
if (!pChild) continue;
pChild->DelayedDelete();
}
}
MenuItem* Menu::AddItem(const Gwen::String& strName, const String& strIconName, Gwen::Event::Handler* pHandler, Gwen::Event::Handler::Function fn)
{
return AddItem(Gwen::Utility::StringToUnicode(strName), Gwen::Utility::StringToUnicode(strIconName), pHandler, fn);
}
void Menu::CloseAll()
{
for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
{
Base* pChild = *it;
MenuItem* pItem = pChild->DynamicCastMenuItem();
if (!pItem) continue;
pItem->CloseMenu();
}
}
bool Menu::IsMenuOpen()
{
for (Base::List::iterator it = m_InnerPanel->Children.begin(); it != m_InnerPanel->Children.end(); ++it)
{
Base* pChild = *it;
MenuItem* pItem = pChild->DynamicCastMenuItem();
if (!pItem) continue;
if (pItem->IsMenuOpen())
return true;
}
return false;
}
void Menu::OnHoverItem(Gwen::Controls::Base* pControl)
{
if (!ShouldHoverOpenMenu()) return;
MenuItem* pItem = pControl->DynamicCastMenuItem();
if (!pItem) return;
if (pItem->IsMenuOpen()) return;
CloseAll();
pItem->OpenMenu();
}
void Menu::Close()
{
SetHidden(true);
}
void Menu::CloseMenus()
{
BaseClass::CloseMenus();
CloseAll();
Close();
}
void Menu::AddDivider()
{
MenuDivider* divider = new MenuDivider(this);
divider->Dock(Pos::Top);
divider->SetMargin(Margin(IconMarginDisabled() ? 0 : 24, 0, 4, 0));
}
void MenuDivider::Render(Gwen::Skin::Base* skin)
{
skin->DrawMenuDivider(this);
}

View file

@ -0,0 +1,83 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_MENU_H
#define GWEN_CONTROLS_MENU_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/MenuItem.h"
#include "Gwen/Controls/ScrollControl.h"
namespace Gwen
{
namespace Controls
{
class MenuItem;
class GWEN_EXPORT Menu : public ScrollControl
{
public:
GWEN_CONTROL(Menu, ScrollControl);
virtual void Render(Skin::Base* skin);
virtual void RenderUnder(Skin::Base* skin);
virtual void Layout(Skin::Base* skin);
virtual MenuItem* AddItem(const Gwen::UnicodeString& strName, const UnicodeString& strIconName, Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::Function fn = NULL);
virtual MenuItem* AddItem(const Gwen::UnicodeString& strName, Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::Function fn = NULL)
{
return AddItem(strName, L"", pHandler, fn);
}
virtual MenuItem* AddItem(const Gwen::String& strName, const String& strIconName, Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::Function fn = NULL);
virtual MenuItem* AddItem(const Gwen::String& strName, Gwen::Event::Handler* pHandler = NULL, Gwen::Event::Handler::Function fn = NULL)
{
return AddItem(strName, "", pHandler, fn);
}
virtual void AddDivider();
void OnHoverItem(Gwen::Controls::Base* pControl);
void CloseAll();
bool IsMenuOpen();
void ClearItems();
virtual void Close();
virtual bool IsMenuComponent() { return true; }
virtual void CloseMenus();
bool IconMarginDisabled() { return m_bDisableIconMargin; }
void SetDisableIconMargin(bool bDisable) { m_bDisableIconMargin = bDisable; }
virtual bool ShouldClip() { return false; }
protected:
virtual bool ShouldHoverOpenMenu() { return true; }
virtual void OnAddItem(MenuItem* item);
bool m_bDisableIconMargin;
};
class GWEN_EXPORT MenuDivider : public Base
{
public:
GWEN_CONTROL_INLINE(MenuDivider, Base)
{
SetHeight(1);
}
void Render(Gwen::Skin::Base* skin);
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,134 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/MenuItem.h"
#include "Gwen/Skin.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(MenuItem)
{
m_Menu = NULL;
m_bOnStrip = false;
m_SubmenuArrow = NULL;
SetTabable(false);
SetCheckable(false);
SetCheck(false);
}
MenuItem::~MenuItem()
{
}
void MenuItem::Render(Skin::Base* skin)
{
skin->DrawMenuItem(this, IsMenuOpen(), m_bCheckable ? m_bChecked : false);
}
void MenuItem::Layout(Skin::Base* skin)
{
BaseClass::Layout(skin);
}
Menu* MenuItem::GetMenu()
{
if (!m_Menu)
{
m_Menu = new Menu(GetCanvas());
m_Menu->SetHidden(true);
if (!m_bOnStrip)
{
m_SubmenuArrow = new Symbol::Arrow(this);
m_SubmenuArrow->Dock(Pos::Right);
m_SubmenuArrow->SetSize(20, 20);
}
Invalidate();
}
return m_Menu;
}
void MenuItem::SetCheck(bool bCheck)
{
if (bCheck == m_bChecked)
return;
m_bChecked = bCheck;
onCheckChange.Call(this);
if (bCheck)
onChecked.Call(this);
else
onUnChecked.Call(this);
}
void MenuItem::OnPress()
{
if (m_Menu)
{
ToggleMenu();
}
else if (!m_bOnStrip)
{
SetCheck(!GetChecked());
onMenuItemSelected.Call(this);
GetCanvas()->CloseMenus();
}
BaseClass::OnPress();
}
void MenuItem::ToggleMenu()
{
if (IsMenuOpen())
CloseMenu();
else
OpenMenu();
}
bool MenuItem::IsMenuOpen()
{
if (!m_Menu) return false;
return !m_Menu->Hidden();
}
void MenuItem::OpenMenu()
{
if (!m_Menu) return;
m_Menu->SetHidden(false);
m_Menu->BringToFront();
Gwen::Point p = LocalPosToCanvas(Gwen::Point(0, 0));
// Strip menus open downwards
if (m_bOnStrip)
{
m_Menu->SetPos(p.x, p.y + Height() + 1);
}
// Submenus open sidewards
else
{
m_Menu->SetPos(p.x + Width(), p.y);
}
// TODO: Option this.
// TODO: Make sure on screen, open the other side of the
// parent if it's better...
}
void MenuItem::CloseMenu()
{
if (!m_Menu) return;
m_Menu->Close();
m_Menu->CloseAll();
}

View file

@ -0,0 +1,65 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_MENUITEM_H
#define GWEN_CONTROLS_MENUITEM_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/Menu.h"
#include "Gwen/Controls/Symbol.h"
namespace Gwen
{
namespace Controls
{
class Menu;
class GWEN_EXPORT MenuItem : public Button
{
public:
GWEN_CONTROL(MenuItem, Button);
virtual ~MenuItem();
virtual void Render(Skin::Base* skin);
virtual void Layout(Skin::Base* skin);
virtual void OnPress();
Menu* GetMenu();
bool IsMenuOpen();
void OpenMenu();
void CloseMenu();
void ToggleMenu();
void SetOnStrip(bool b) { m_bOnStrip = b; }
bool OnStrip() { return m_bOnStrip; }
virtual void SetCheckable(bool bCheck) { m_bCheckable = bCheck; }
virtual void SetCheck(bool bCheck);
virtual bool GetChecked() { return m_bChecked; }
Gwen::Event::Caller onMenuItemSelected;
Gwen::Event::Caller onChecked;
Gwen::Event::Caller onUnChecked;
Gwen::Event::Caller onCheckChange;
private:
Menu* m_Menu;
bool m_bOnStrip;
bool m_bCheckable;
bool m_bChecked;
Symbol::Arrow* m_SubmenuArrow;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,43 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/MenuStrip.h"
#include "Gwen/Skin.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(MenuStrip)
{
SetBounds(0, 0, 200, 22);
Dock(Pos::Top);
m_InnerPanel->SetPadding(Padding(5, 2, 2, 2));
}
void MenuStrip::Render(Skin::Base* skin)
{
skin->DrawMenuStrip(this);
}
void MenuStrip::Layout(Skin::Base* /*skin*/)
{
//TODO: We don't want to do vertical sizing the same as Menu, do nothing for now
}
void MenuStrip::OnAddItem(MenuItem* item)
{
item->Dock(Pos::Left);
item->SetPadding(Padding(5, 0, 5, 0));
item->SizeToContents();
item->SetOnStrip(true);
item->onHoverEnter.Add(this, &Menu::OnHoverItem);
}
bool MenuStrip::ShouldHoverOpenMenu()
{
return IsMenuOpen();
}

View file

@ -0,0 +1,36 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_MENUSTRIP_H
#define GWEN_CONTROLS_MENUSTRIP_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Menu.h"
#include "Gwen/Controls/MenuItem.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT MenuStrip : public Menu
{
GWEN_CONTROL(MenuStrip, Menu);
virtual void Render(Skin::Base* skin);
virtual void RenderUnder(Skin::Base* /*skin*/) {}
virtual void Layout(Skin::Base* skin);
protected:
virtual void OnAddItem(MenuItem* item);
virtual bool ShouldHoverOpenMenu();
virtual void Close() {}
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,36 @@
#pragma once
#ifndef GWEN_CONTROLS_MODAL_H
#define GWEN_CONTROLS_MODAL_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace ControlsInternal
{
class Modal : public Controls::Base
{
GWEN_CONTROL_INLINE(Modal, Controls::Base)
{
SetKeyboardInputEnabled(true);
SetMouseInputEnabled(true);
SetShouldDrawBackground(true);
}
virtual void Layout(Skin::Base* /*skin*/)
{
SetBounds(0, 0, GetCanvas()->Width(), GetCanvas()->Height());
}
virtual void Render(Skin::Base* skin)
{
if (!ShouldDrawBackground()) return;
skin->DrawModalControl(this);
}
};
} // namespace ControlsInternal
} // namespace Gwen
#endif

View file

@ -0,0 +1,112 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Utility.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/NumericUpDown.h"
#include "Gwen/Controls/Layout/Splitter.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(NumericUpDown)
{
SetSize(100, 20);
Layout::Splitter* pSplitter = new Layout::Splitter(this);
pSplitter->Dock(Pos::Right);
pSplitter->SetSize(13, 13);
NumericUpDownButton_Up* pButtonUp = new NumericUpDownButton_Up(pSplitter);
pButtonUp->onPress.Add(this, &NumericUpDown::OnButtonUp);
pButtonUp->SetTabable(false);
pSplitter->SetPanel(0, pButtonUp);
NumericUpDownButton_Down* pButtonDown = new NumericUpDownButton_Down(pSplitter);
pButtonDown->onPress.Add(this, &NumericUpDown::OnButtonDown);
pButtonDown->SetTabable(false);
pButtonUp->SetPadding(Padding(0, 1, 1, 0));
pSplitter->SetPanel(1, pButtonDown);
m_iMax = 100;
m_iMin = 0;
m_iNumber = 0;
SetText("0");
}
void NumericUpDown::OnButtonUp(Base* /*control*/)
{
SyncNumberFromText();
SetValue(m_iNumber + 1);
}
void NumericUpDown::OnButtonDown(Base* /*control*/)
{
SyncNumberFromText();
SetValue(m_iNumber - 1);
}
void NumericUpDown::SyncTextFromNumber()
{
SetText(Utility::ToString(m_iNumber));
}
void NumericUpDown::SyncNumberFromText()
{
SetValue((int)GetFloatFromText());
}
void NumericUpDown::SetMin(int i)
{
m_iMin = i;
}
void NumericUpDown::SetMax(int i)
{
m_iMax = i;
}
void NumericUpDown::SetValue(int i)
{
if (i > m_iMax) i = m_iMax;
if (i < m_iMin) i = m_iMin;
if (m_iNumber == i)
{
return;
}
m_iNumber = i;
// Don't update the text if we're typing in it..
if (!HasFocus())
{
SyncTextFromNumber();
}
OnChange();
}
void NumericUpDown::OnChange()
{
onChanged.Call(this);
}
void NumericUpDown::OnTextChanged()
{
BaseClass::OnTextChanged();
SyncNumberFromText();
}
void NumericUpDown::OnEnter()
{
SyncNumberFromText();
SyncTextFromNumber();
}

View file

@ -0,0 +1,78 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_NUMERICUPDOWN_H
#define GWEN_CONTROLS_NUMERICUPDOWN_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/TextBox.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT NumericUpDownButton_Up : public Button
{
GWEN_CONTROL_INLINE(NumericUpDownButton_Up, Button) {}
virtual void Render(Skin::Base* skin)
{
skin->DrawNumericUpDownButton(this, m_bDepressed, true);
}
};
class GWEN_EXPORT NumericUpDownButton_Down : public Button
{
GWEN_CONTROL_INLINE(NumericUpDownButton_Down, Button) {}
virtual void Render(Skin::Base* skin)
{
skin->DrawNumericUpDownButton(this, m_bDepressed, false);
}
};
class GWEN_EXPORT NumericUpDown : public TextBoxNumeric
{
public:
GWEN_CONTROL(NumericUpDown, TextBoxNumeric);
virtual void SetMin(int i);
virtual void SetMax(int i);
virtual void SetValue(int i);
Event::Caller onChanged;
private:
virtual void OnEnter();
virtual void OnChange();
virtual void OnTextChanged();
virtual void OnButtonUp(Base* control);
virtual void OnButtonDown(Base* control);
virtual bool OnKeyUp(bool bDown)
{
if (bDown) OnButtonUp(NULL);
return true;
}
virtual bool OnKeyDown(bool bDown)
{
if (bDown) OnButtonDown(NULL);
return true;
}
virtual void SyncTextFromNumber();
virtual void SyncNumberFromText();
int m_iNumber;
int m_iMax;
int m_iMin;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,124 @@
#include "Gwen/Controls/PanelListPanel.h"
using namespace Gwen;
using namespace Controls;
GWEN_CONTROL_CONSTRUCTOR(PanelListPanel)
{
m_bVertical = false;
m_bSizeToChildren = true;
m_iControlSpacing = 5;
m_iLineSpacing = 5;
m_bWrapping = true;
}
void PanelListPanel::Render(Gwen::Skin::Base* /*skin*/)
{
}
Gwen::Point PanelListPanel::GetBiggestChildSize()
{
int width = 0;
int height = 0;
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
Controls::Base* pChild = *it;
if (pChild->Width() > width)
width = pChild->Width();
if (pChild->Height() > height)
height = pChild->Height();
}
return Gwen::Point(width, height);
}
void PanelListPanel::DoVerticalLayout()
{
int panelWidth = 0;
int panelX = GetPadding().left;
int panelY = GetPadding().top;
int lastPanelY = panelY;
int testWrap = 0;
Gwen::Point childSize = GetBiggestChildSize();
//Lay my children out accordingly
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
Controls::Base* pChild = *it;
testWrap = lastPanelY + m_iControlSpacing + childSize.y;
if (m_bWrapping && testWrap > Height() - GetPadding().bottom)
{
panelY = GetPadding().top;
panelX = GetPadding().left + panelWidth + m_iLineSpacing;
lastPanelY = panelY + m_iControlSpacing + childSize.y;
}
else
{
panelY = lastPanelY;
lastPanelY = testWrap;
}
pChild->SetPos(panelX, panelY);
if (pChild->X() + childSize.x > panelWidth)
panelWidth = pChild->X() + childSize.x;
}
if (m_bSizeToChildren)
{
Gwen::Point childrenSizeTotal = ChildrenSize();
SetSize(childrenSizeTotal.x, Height());
}
}
void PanelListPanel::DoHorizontalLayout()
{
int panelHeight = 0;
int panelX = GetPadding().left;
int panelY = GetPadding().top;
int lastPanelX = panelX;
int testWrap = 0;
Gwen::Point childSize = GetBiggestChildSize();
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
Controls::Base* pChild = *it;
testWrap = lastPanelX + m_iControlSpacing + childSize.x;
if (m_bWrapping && testWrap > Width() - GetPadding().right)
{
panelX = GetPadding().left;
panelY = GetPadding().top + panelHeight + m_iLineSpacing;
lastPanelX = panelX + m_iControlSpacing + childSize.x;
}
else
{
panelX = lastPanelX;
lastPanelX = testWrap;
}
pChild->SetPos(panelX, panelY);
if (pChild->Y() + childSize.y > panelHeight)
panelHeight = pChild->Y() + childSize.y;
}
if (m_bSizeToChildren)
{
Gwen::Point childrenSizeTotal = ChildrenSize();
SetSize(Width(), childrenSizeTotal.y);
}
}
void PanelListPanel::Layout(Skin::Base* skin)
{
BaseClass::Layout(skin);
if (IsHorizontalLayout())
DoHorizontalLayout();
else
DoVerticalLayout();
}

View file

@ -0,0 +1,52 @@
#pragma once
#ifndef GWEN_CONTROLS_PANELLISTPANEL_H
#define GWEN_CONTROLS_PANELLISTPANEL_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Base.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT PanelListPanel : public Controls::Base
{
public:
GWEN_CONTROL(PanelListPanel, Controls::Base);
void Render(Gwen::Skin::Base* skin);
void Layout(Skin::Base* skin);
void DoHorizontalLayout();
void DoVerticalLayout();
bool IsVerticalLayout() { return m_bVertical; }
bool IsHorizontalLayout() { return !m_bVertical; }
void SetVertical()
{
m_bVertical = true;
Invalidate();
}
void SetHorizontal()
{
m_bVertical = false;
Invalidate();
}
void SetSizeToChildren(bool bShould) { m_bSizeToChildren = bShould; }
void SetControlSpacing(int spacing) { m_iControlSpacing = spacing; }
void SetLineSpacing(int spacing) { m_iLineSpacing = spacing; }
void SetWrapping(bool wrap) { m_bWrapping = wrap; }
Gwen::Point GetBiggestChildSize();
protected:
bool m_bVertical;
bool m_bSizeToChildren;
int m_iControlSpacing;
int m_iLineSpacing;
bool m_bWrapping;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,47 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ScrollControl.h"
#include "Gwen/Controls/ProgressBar.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(ProgressBar)
{
SetMouseInputEnabled(true);
SetBounds(Gwen::Rect(0, 0, 128, 32));
SetTextPadding(Padding(3, 3, 3, 3));
SetHorizontal();
SetAlignment(Gwen::Pos::Center);
m_fProgress = 0.0f;
m_bAutoLabel = true;
}
void ProgressBar::SetValue(float val)
{
if (val < 0)
val = 0;
if (val > 1)
val = 1;
m_fProgress = val;
if (m_bAutoLabel)
{
int displayVal = m_fProgress * 100;
SetText(Utility::ToString(displayVal) + "%");
}
}
void ProgressBar::Render(Skin::Base* skin)
{
skin->DrawProgressBar(this, m_bHorizontal, m_fProgress);
}

View file

@ -0,0 +1,42 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_PROGRESSBAR_H
#define GWEN_CONTROLS_PROGRESSBAR_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT ProgressBar : public Label
{
public:
GWEN_CONTROL(ProgressBar, Label);
virtual void Render(Skin::Base* skin);
virtual void SetVertical() { m_bHorizontal = false; }
virtual void SetHorizontal() { m_bHorizontal = true; }
virtual void SetValue(float val);
virtual float GetValue() const { return m_fProgress; }
virtual void SetAutoLabel(bool b) { m_bAutoLabel = b; }
protected:
float m_fProgress;
bool m_bHorizontal;
bool m_bAutoLabel;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,123 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Properties.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(Properties)
{
m_SplitterBar = new SplitterBar(this);
m_SplitterBar->SetPos(80, 0);
m_SplitterBar->SetCursor(Gwen::CursorType::SizeWE);
m_SplitterBar->onDragged.Add(this, &Properties::OnSplitterMoved);
m_SplitterBar->SetShouldDrawBackground(false);
}
void Properties::PostLayout(Gwen::Skin::Base* /*skin*/)
{
m_SplitterBar->SetHeight(0);
if (SizeToChildren(false, true))
{
InvalidateParent();
}
m_SplitterBar->SetSize(3, Height());
}
void Properties::OnSplitterMoved(Controls::Base* /*control*/)
{
InvalidateChildren();
}
int Properties::GetSplitWidth()
{
return m_SplitterBar->X();
}
PropertyRow* Properties::Add(const UnicodeString& text, const UnicodeString& value)
{
Property::Base* pProp = new Property::Text(this);
pProp->SetPropertyValue(value);
return Add(text, pProp);
}
PropertyRow* Properties::Add(const String& text, const String& value)
{
return Add(Gwen::Utility::StringToUnicode(text), Gwen::Utility::StringToUnicode(value));
}
PropertyRow* Properties::Add(const UnicodeString& text, Property::Base* pProp)
{
PropertyRow* row = new PropertyRow(this);
row->Dock(Pos::Top);
row->GetLabel()->SetText(text);
row->SetProperty(pProp);
m_SplitterBar->BringToFront();
return row;
}
PropertyRow* Properties::Add(const String& text, Property::Base* pProp)
{
return Add(Gwen::Utility::StringToUnicode(text), pProp);
}
void Properties::Clear()
{
Base::List ChildListCopy = Children;
for (Base::List::iterator it = ChildListCopy.begin(); it != ChildListCopy.end(); ++it)
{
PropertyRow* row = (*it)->DynamicCastPropertyRow();
if (!row) continue;
row->DelayedDelete();
}
}
GWEN_CONTROL_CONSTRUCTOR(PropertyRow)
{
m_Property = NULL;
m_Label = new Label(this);
m_Label->SetAlignment(Pos::CenterV | Pos::Left);
m_Label->Dock(Pos::Left);
m_Label->SetMargin(Margin(2, 0, 0, 0));
SetHeight(16);
}
void PropertyRow::Render(Gwen::Skin::Base* skin)
{
skin->DrawPropertyRow(this, m_Label->Right(), m_Property->IsEditing());
}
void PropertyRow::Layout(Gwen::Skin::Base* /*skin*/)
{
Properties* pParent = GetParent()->DynamicCastProperties();
if (!pParent) return;
m_Label->SetWidth(pParent->GetSplitWidth());
}
void PropertyRow::SetProperty(Property::Base* prop)
{
m_Property = prop;
m_Property->SetParent(this);
m_Property->Dock(Pos::Fill);
m_Property->onChange.Add(this, &ThisClass::OnPropertyValueChanged);
}
void PropertyRow::OnPropertyValueChanged(Gwen::Controls::Base* /*control*/)
{
onChange.Call(this);
}

View file

@ -0,0 +1,69 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_PROPERTIES_H
#define GWEN_CONTROLS_PROPERTIES_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Controls/Property/BaseProperty.h"
#include "Gwen/Controls/Property/Text.h"
#include "Gwen/Controls/SplitterBar.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace Controls
{
class PropertyRow;
class GWEN_EXPORT Properties : public Base
{
public:
GWEN_CONTROL(Properties, Base);
virtual void PostLayout(Gwen::Skin::Base* skin);
PropertyRow* Add(const UnicodeString& text, const UnicodeString& value = L"");
PropertyRow* Add(const String& text, const String& value = "");
PropertyRow* Add(const UnicodeString& text, Property::Base* pProp);
PropertyRow* Add(const String& text, Property::Base* pProp);
virtual int GetSplitWidth();
virtual void Clear();
protected:
virtual void OnSplitterMoved(Controls::Base* control);
Controls::SplitterBar* m_SplitterBar;
};
class GWEN_EXPORT PropertyRow : public Base
{
public:
GWEN_CONTROL(PropertyRow, Base);
virtual Label* GetLabel() { return m_Label; }
virtual void SetProperty(Property::Base* prop);
virtual Property::Base* GetProperty() { return m_Property; }
virtual void Layout(Gwen::Skin::Base* skin);
virtual void Render(Gwen::Skin::Base* skin);
Event::Caller onChange;
protected:
void OnPropertyValueChanged(Gwen::Controls::Base* control);
Label* m_Label;
Property::Base* m_Property;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,58 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_PROPERTY_BASEPROPERTY_H
#define GWEN_CONTROLS_PROPERTY_BASEPROPERTY_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Utility.h"
namespace Gwen
{
namespace Controls
{
namespace Property
{
class GWEN_EXPORT Base : public Gwen::Controls::Base
{
public:
GWEN_CONTROL_INLINE(Base, Gwen::Controls::Base) {}
virtual String GetPropertyValueAnsi()
{
return Gwen::Utility::UnicodeToString(GetPropertyValue());
}
virtual void SetPropertyValue(const String& v, bool bFireChangeEvents = false)
{
SetPropertyValue(Gwen::Utility::StringToUnicode(v), bFireChangeEvents);
}
virtual UnicodeString GetPropertyValue() = 0;
virtual void SetPropertyValue(const UnicodeString& v, bool bFireChangeEvents = false) = 0;
virtual bool IsEditing() = 0;
virtual void DoChanged()
{
onChange.Call(this);
}
virtual void OnPropertyValueChanged(Gwen::Controls::Base* /*control*/)
{
DoChanged();
}
Event::Caller onChange;
};
} // namespace Property
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,79 @@
#pragma once
#ifndef GWEN_CONTROLS_PROPERTY_COLORSELECTOR_H
#define GWEN_CONTROLS_PROPERTY_COLORSELECTOR_H
#include "Gwen/Controls/Properties.h"
#include "Gwen/Controls/WindowControl.h"
#include "Gwen/Controls/HSVColorPicker.h"
namespace Gwen
{
namespace Controls
{
namespace Property
{
class ColorSelector : public Property::Text
{
public:
GWEN_CONTROL_INLINE(ColorSelector, Property::Text)
{
m_Button = new Button(this);
m_Button->Dock(Pos::Right);
m_Button->SetWidth(20);
m_Button->onPress.Add(this, &ThisClass::OnButtonPress);
}
void OnButtonPress(Controls::Base* control)
{
Gwen::Controls::WindowControl* wind = new Gwen::Controls::WindowControl(GetCanvas());
wind->SetTitle(L"Color Selection");
wind->SetSize(256, 180);
wind->SetPos(GetCanvas()->Width() * 0.5 - 128, GetCanvas()->Height() * 0.5 - 128);
wind->SetDeleteOnClose(true);
wind->DisableResizing();
wind->MakeModal(true);
Gwen::Controls::HSVColorPicker* picker = new Gwen::Controls::HSVColorPicker(wind);
picker->SetName("picker");
float defaultColor[3];
Gwen::Utility::Strings::To::Floats(Gwen::Utility::UnicodeToString(m_TextBox->GetText()), defaultColor, 3);
picker->SetColor(Gwen::Color(defaultColor[0], defaultColor[1], defaultColor[2], 255), false, true);
picker->onColorChanged.Add(this, &ThisClass::ColorChanged);
}
void ColorChanged(Controls::Base* control)
{
Gwen::Controls::HSVColorPicker* picker = control->DynamicCastHSVColorPicker();
Gwen::String colorStr;
colorStr += Gwen::Utility::ToString((int)picker->GetColor().r) + " ";
colorStr += Gwen::Utility::ToString((int)picker->GetColor().g) + " ";
colorStr += Gwen::Utility::ToString((int)picker->GetColor().b);
m_TextBox->SetText(colorStr);
DoChanged();
}
virtual UnicodeString GetPropertyValue()
{
return m_TextBox->GetText();
}
virtual void SetPropertyValue(const UnicodeString& v, bool bFireChangeEvents)
{
m_TextBox->SetText(v, bFireChangeEvents);
}
virtual bool IsEditing()
{
return m_TextBox == Gwen::KeyboardFocus;
}
Button* m_Button;
};
} // namespace Property
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,51 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_PROPERTY_TEXT_H
#define GWEN_CONTROLS_PROPERTY_TEXT_H
#include "Gwen/Controls/Property/BaseProperty.h"
#include "Gwen/Controls/TextBox.h"
namespace Gwen
{
namespace Controls
{
namespace Property
{
class GWEN_EXPORT Text : public Property::Base
{
public:
GWEN_CONTROL_INLINE(Text, Property::Base)
{
m_TextBox = new TextBox(this);
m_TextBox->Dock(Pos::Fill);
m_TextBox->SetShouldDrawBackground(false);
m_TextBox->onTextChanged.Add(this, &BaseClass::OnPropertyValueChanged);
}
virtual UnicodeString GetPropertyValue()
{
return m_TextBox->GetText();
}
virtual void SetPropertyValue(const UnicodeString& v, bool bFireChangeEvents)
{
m_TextBox->SetText(v, bFireChangeEvents);
}
virtual bool IsEditing()
{
return m_TextBox->HasFocus();
}
TextBox* m_TextBox;
};
} // namespace Property
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,57 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_PROPERTYTREE_H
#define GWEN_CONTROLS_PROPERTYTREE_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/TreeControl.h"
#include "Gwen/Controls/Properties.h"
namespace Gwen
{
namespace Controls
{
class PropertyTreeNode : public TreeNode
{
public:
GWEN_CONTROL_INLINE(PropertyTreeNode, TreeNode)
{
}
virtual void Render(Skin::Base* skin)
{
skin->DrawPropertyTreeNode(this, m_InnerPanel->X(), m_InnerPanel->Y());
}
};
class PropertyTree : public TreeControl
{
public:
GWEN_CONTROL_INLINE(PropertyTree, TreeControl)
{
}
Properties* Add(const UnicodeString& text)
{
TreeNode* node = new PropertyTreeNode(this);
node->SetText(text);
node->Dock(Pos::Top);
Properties* props = new Properties(node);
props->Dock(Pos::Top);
return props;
}
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,22 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/RadioButton.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(RadioButton)
{
SetSize(11, 11);
SetMouseInputEnabled(true);
SetTabable(false);
}
void RadioButton::Render(Skin::Base* skin)
{
skin->DrawRadioButton(this, IsChecked(), IsDepressed());
}

View file

@ -0,0 +1,79 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_RADIOBUTTON_H
#define GWEN_CONTROLS_RADIOBUTTON_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/CheckBox.h"
#include "Gwen/Controls/LabelClickable.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT RadioButton : public CheckBox
{
GWEN_CONTROL(RadioButton, CheckBox);
virtual void Render(Skin::Base* skin);
private:
// From CheckBox
virtual bool AllowUncheck() { return false; }
};
class GWEN_EXPORT LabeledRadioButton : public Base
{
public:
GWEN_CONTROL_INLINE(LabeledRadioButton, Base)
{
SetSize(200, 19);
m_RadioButton = new RadioButton(this);
m_RadioButton->Dock(Pos::Left);
m_RadioButton->SetMargin(Margin(0, 4, 2, 4));
m_RadioButton->SetTabable(false);
m_RadioButton->SetKeyboardInputEnabled(false);
m_Label = new LabelClickable(this);
m_Label->SetAlignment(Pos::CenterV | Pos::Left);
m_Label->SetText("Radio Button");
m_Label->Dock(Pos::Fill);
m_Label->onPress.Add(m_RadioButton, &CheckBox::ReceiveEventPress);
m_Label->SetTabable(false);
m_Label->SetKeyboardInputEnabled(false);
}
void RenderFocus(Gwen::Skin::Base* skin)
{
if (Gwen::KeyboardFocus != this) return;
if (!IsTabable()) return;
skin->DrawKeyboardHighlight(this, GetRenderBounds(), 0);
}
virtual RadioButton* GetRadioButton() { return m_RadioButton; }
virtual LabelClickable* GetLabel() { return m_Label; }
virtual bool OnKeySpace(bool bDown)
{
if (bDown) m_RadioButton->SetChecked(!m_RadioButton->IsChecked());
return true;
}
virtual void Select() { m_RadioButton->SetChecked(true); }
private:
RadioButton* m_RadioButton;
LabelClickable* m_Label;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,72 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/RadioButtonController.h"
#include "Gwen/Controls/RadioButton.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(RadioButtonController)
{
m_Selected = NULL;
SetTabable(false);
SetKeyboardInputEnabled(false);
}
void RadioButtonController::OnRadioClicked(Gwen::Controls::Base* pFromPanel)
{
RadioButton* pCheckedRadioButton = pFromPanel->DynamicCastRadioButton();
//Iterate through all other buttons and set them to false;
for (Base::List::iterator iter = Children.begin(); iter != Children.end(); ++iter)
{
Base* pChild = *iter;
LabeledRadioButton* pLRB = pChild->DynamicCastLabeledRadioButton();
if (pLRB)
{
RadioButton* pChildRadioButton = pLRB->GetRadioButton();
if (pChildRadioButton == pCheckedRadioButton)
{
m_Selected = pLRB;
}
else
{
pLRB->GetRadioButton()->SetChecked(false);
}
}
}
OnChange();
}
void RadioButtonController::OnChange()
{
onSelectionChange.Call(this);
}
LabeledRadioButton* RadioButtonController::AddOption(const Gwen::String& strText, const Gwen::String& strOptionName)
{
return AddOption(Gwen::Utility::StringToUnicode(strText), strOptionName);
}
LabeledRadioButton* RadioButtonController::AddOption(const Gwen::UnicodeString& strText, const Gwen::String& strOptionName)
{
LabeledRadioButton* lrb = new LabeledRadioButton(this);
lrb->SetName(strOptionName);
lrb->GetLabel()->SetText(strText);
lrb->GetRadioButton()->onChecked.Add(this, &RadioButtonController::OnRadioClicked);
lrb->Dock(Pos::Top);
lrb->SetMargin(Margin(0, 1, 0, 1));
lrb->SetKeyboardInputEnabled(false);
lrb->SetTabable(false);
Invalidate();
return lrb;
}

View file

@ -0,0 +1,44 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_RADIOBOTTONCONTROLLER_H
#define GWEN_CONTROLS_RADIOBOTTONCONTROLLER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Controls/RadioButton.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT RadioButtonController : public Base
{
public:
GWEN_CONTROL(RadioButtonController, Base);
virtual void Render(Skin::Base* /*skin*/){};
virtual void OnRadioClicked(Base* pFromPanel);
virtual void OnChange();
virtual LabeledRadioButton* AddOption(const Gwen::String& strText, const Gwen::String& strOptionName = "");
virtual LabeledRadioButton* AddOption(const Gwen::UnicodeString& strText, const Gwen::String& strOptionName = "");
virtual LabeledRadioButton* GetSelected() { return m_Selected; }
virtual String GetSelectedName() { return m_Selected->GetName(); }
virtual UnicodeString GetSelectedLabel() { return m_Selected->GetLabel()->GetText(); }
Event::Caller onSelectionChange;
private:
LabeledRadioButton* m_Selected;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,109 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ImagePanel.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Controls/Resizer.h"
#include "Gwen/Controls/ResizableControl.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(ResizableControl)
{
m_bResizable = true;
m_MinimumSize = Gwen::Point(5, 5);
m_bClampMovement = false;
Resizer* resizerBottom = new Resizer(this);
resizerBottom->Dock(Pos::Bottom);
resizerBottom->SetResizeDir(Pos::Bottom);
resizerBottom->SetTarget(this);
resizerBottom->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerBottomLeft = new Resizer(resizerBottom);
resizerBottomLeft->Dock(Pos::Left);
resizerBottomLeft->SetResizeDir(Pos::Bottom | Pos::Left);
resizerBottomLeft->SetTarget(this);
resizerBottomLeft->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerBottomRight = new Resizer(resizerBottom);
resizerBottomRight->Dock(Pos::Right);
resizerBottomRight->SetResizeDir(Pos::Bottom | Pos::Right);
resizerBottomRight->SetTarget(this);
resizerBottomRight->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerTop = new Resizer(this);
resizerTop->Dock(Pos::Top);
resizerTop->SetResizeDir(Pos::Top);
resizerTop->SetTarget(this);
resizerTop->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerTopLeft = new Resizer(resizerTop);
resizerTopLeft->Dock(Pos::Left);
resizerTopLeft->SetResizeDir(Pos::Top | Pos::Left);
resizerTopLeft->SetTarget(this);
resizerTopLeft->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerTopRight = new Resizer(resizerTop);
resizerTopRight->Dock(Pos::Right);
resizerTopRight->SetResizeDir(Pos::Top | Pos::Right);
resizerTopRight->SetTarget(this);
resizerTopRight->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerLeft = new Resizer(this);
resizerLeft->Dock(Pos::Left);
resizerLeft->SetResizeDir(Pos::Left);
resizerLeft->SetTarget(this);
resizerLeft->onResize.Add(this, &ResizableControl::OnResizedInternal);
Resizer* resizerRight = new Resizer(this);
resizerRight->Dock(Pos::Right);
resizerRight->SetResizeDir(Pos::Right);
resizerRight->SetTarget(this);
resizerRight->onResize.Add(this, &ResizableControl::OnResizedInternal);
}
void ResizableControl::DisableResizing()
{
for (Base::List::iterator it = Children.begin(); it != Children.end(); ++it)
{
Resizer* resizer = (*it)->DynamicCastResizer();
if (!resizer) continue;
resizer->SetMouseInputEnabled(false);
resizer->SetHidden(true);
SetPadding(Padding(resizer->Width(), resizer->Width(), resizer->Width(), resizer->Width()));
}
}
bool ResizableControl::SetBounds(int x, int y, int w, int h)
{
Gwen::Point minSize = GetMinimumSize();
// Clamp Minimum Size
if (w < minSize.x) w = minSize.x;
if (h < minSize.y) h = minSize.y;
// Clamp to parent's window
Base* pParent = GetParent();
if (pParent && m_bClampMovement)
{
if (x + w > pParent->Width()) x = pParent->Width() - w;
if (x < 0) x = 0;
if (y + h > pParent->Height()) y = pParent->Height() - h;
if (y < 0) y = 0;
}
return BaseClass::SetBounds(x, y, w, h);
}
void ResizableControl::OnResizedInternal(Controls::Base* /*pControl*/)
{
onResize.Call(this);
OnResized();
}

View file

@ -0,0 +1,51 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_RESIZABLECONTROL_H
#define GWEN_CONTROLS_RESIZABLECONTROL_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/Dragger.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT ResizableControl : public Base
{
public:
GWEN_CONTROL(ResizableControl, Base);
virtual void SetClampMovement(bool shouldClamp) { m_bClampMovement = shouldClamp; }
virtual bool GetClampMovement() { return m_bClampMovement; }
virtual void SetMinimumSize(const Gwen::Point& minSize) { m_MinimumSize = minSize; }
virtual Gwen::Point GetMinimumSize() { return m_MinimumSize; }
virtual void DisableResizing();
virtual bool SetBounds(int x, int y, int w, int h);
virtual void OnResized(){};
Event::Caller onResize;
protected:
void OnResizedInternal(Controls::Base* pControl);
Gwen::Point m_MinimumSize;
bool m_bClampMovement;
bool m_bResizable;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,115 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/Resizer.h"
using namespace Gwen;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(Resizer)
{
m_iResizeDir = Pos::Left;
SetMouseInputEnabled(true);
SetSize(6, 6);
}
void Resizer::OnMouseMoved(int x, int y, int /*deltaX*/, int /*deltaY*/)
{
if (!m_pTarget) return;
if (!m_bDepressed) return;
// Gwen::Rect oldBounds = m_pTarget->GetBounds();
Gwen::Rect pBounds = m_pTarget->GetBounds();
Gwen::Point pntMin = m_pTarget->GetMinimumSize();
Gwen::Point pCursorPos = m_pTarget->CanvasPosToLocal(Gwen::Point(x, y));
Gwen::Point pDelta = m_pTarget->LocalPosToCanvas(m_HoldPos);
pDelta.x -= x;
pDelta.y -= y;
if (m_iResizeDir & Pos::Left)
{
pBounds.x -= pDelta.x;
pBounds.w += pDelta.x;
// Conform to minimum size here so we don't
// go all weird when we snap it in the base conrt
if (pBounds.w < pntMin.x)
{
int diff = pntMin.x - pBounds.w;
pBounds.w += diff;
pBounds.x -= diff;
}
}
if (m_iResizeDir & Pos::Top)
{
pBounds.y -= pDelta.y;
pBounds.h += pDelta.y;
// Conform to minimum size here so we don't
// go all weird when we snap it in the base conrt
if (pBounds.h < pntMin.y)
{
int diff = pntMin.y - pBounds.h;
pBounds.h += diff;
pBounds.y -= diff;
}
}
if (m_iResizeDir & Pos::Right)
{
// This is complicated.
// Basically we want to use the HoldPos, so it doesn't snap to the edge of the control
// But we need to move the HoldPos with the window movement. Yikes.
// I actually think this might be a big hack around the way this control works with regards
// to the holdpos being on the parent panel.
int woff = pBounds.w - m_HoldPos.x;
int diff = pBounds.w;
pBounds.w = pCursorPos.x + woff;
if (pBounds.w < pntMin.x) pBounds.w = pntMin.x;
diff -= pBounds.w;
m_HoldPos.x -= diff;
}
if (m_iResizeDir & Pos::Bottom)
{
int hoff = pBounds.h - m_HoldPos.y;
int diff = pBounds.h;
pBounds.h = pCursorPos.y + hoff;
if (pBounds.h < pntMin.y) pBounds.h = pntMin.y;
diff -= pBounds.h;
m_HoldPos.y -= diff;
}
m_pTarget->SetBounds(pBounds);
onResize.Call(this);
}
void Resizer::SetResizeDir(int dir)
{
m_iResizeDir = dir;
if ((dir & Pos::Left && dir & Pos::Top) || (dir & Pos::Right && dir & Pos::Bottom))
return SetCursor(Gwen::CursorType::SizeNWSE);
if ((dir & Pos::Right && dir & Pos::Top) || (dir & Pos::Left && dir & Pos::Bottom))
return SetCursor(Gwen::CursorType::SizeNESW);
if (dir & Pos::Right || dir & Pos::Left)
return SetCursor(Gwen::CursorType::SizeWE);
if (dir & Pos::Top || dir & Pos::Bottom)
return SetCursor(Gwen::CursorType::SizeNS);
}

View file

@ -0,0 +1,35 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_RESIZER_H
#define GWEN_CONTROLS_RESIZER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/Dragger.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT Resizer : public Dragger
{
public:
GWEN_CONTROL(Resizer, Dragger);
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);
virtual void SetResizeDir(int dir);
Event::Caller onResize;
protected:
int m_iResizeDir;
};
} // namespace ControlsInternal
} // namespace Gwen
#endif

View file

@ -0,0 +1,207 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Controls/RichLabel.h"
#include "Gwen/Controls/Label.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
const unsigned char Type_Text = 0;
const unsigned char Type_Newline = 1;
GWEN_CONTROL_CONSTRUCTOR(RichLabel)
{
m_bNeedsRebuild = false;
}
void RichLabel::AddLineBreak()
{
DividedText t;
t.type = Type_Newline;
m_TextBlocks.push_back(t);
}
void RichLabel::AddText(const Gwen::TextObject& text, Gwen::Color color, Gwen::Font* font)
{
if (text.m_Data.size() == 0) return;
Gwen::Utility::Strings::UnicodeList lst;
Gwen::Utility::Strings::Split(text.GetUnicode(), L"\n", lst, false);
for (size_t i = 0; i < lst.size(); i++)
{
if (i > 0) AddLineBreak();
DividedText t;
t.type = Type_Text;
t.text = lst[i];
t.color = color;
t.font = font;
m_TextBlocks.push_back(t);
m_bNeedsRebuild = true;
Invalidate();
}
}
bool RichLabel::SizeToChildren(bool w, bool h)
{
Rebuild();
return BaseClass::SizeToChildren(w, h);
}
void RichLabel::SplitLabel(const Gwen::UnicodeString& text, Gwen::Font* pFont, const DividedText& txt, int& x, int& y, int& lineheight)
{
Gwen::Utility::Strings::UnicodeList lst;
Gwen::Utility::Strings::Split(text, L" ", lst, true);
if (lst.size() == 0) return;
int iSpaceLeft = Width() - x;
// Does the whole word fit in?
{
Gwen::Point StringSize = GetSkin()->GetRender()->MeasureText(pFont, text);
if (iSpaceLeft > StringSize.x)
{
return CreateLabel(text, txt, x, y, lineheight, true);
}
}
// If the first word is bigger than the line, just give up.
{
Gwen::Point WordSize = GetSkin()->GetRender()->MeasureText(pFont, lst[0]);
if (WordSize.x >= iSpaceLeft)
{
CreateLabel(lst[0], txt, x, y, lineheight, true);
if (lst[0].size() >= text.size()) return;
Gwen::UnicodeString LeftOver = text.substr(lst[0].size() + 1);
return SplitLabel(LeftOver, pFont, txt, x, y, lineheight);
}
}
Gwen::UnicodeString strNewString = L"";
for (size_t i = 0; i < lst.size(); i++)
{
Gwen::Point WordSize = GetSkin()->GetRender()->MeasureText(pFont, strNewString + lst[i]);
if (WordSize.x > iSpaceLeft)
{
CreateLabel(strNewString, txt, x, y, lineheight, true);
x = 0;
y += lineheight;
break;
;
}
strNewString += lst[i];
}
Gwen::UnicodeString LeftOver = text.substr(strNewString.size() + 1);
return SplitLabel(LeftOver, pFont, txt, x, y, lineheight);
}
void RichLabel::CreateLabel(const Gwen::UnicodeString& text, const DividedText& txt, int& x, int& y, int& lineheight, bool NoSplit)
{
//
// Use default font or is one set?
//
Gwen::Font* pFont = GetSkin()->GetDefaultFont();
if (txt.font) pFont = txt.font;
//
// This string is too long for us, split it up.
//
Gwen::Point p = GetSkin()->GetRender()->MeasureText(pFont, text);
if (lineheight == -1)
{
lineheight = p.y;
}
if (!NoSplit)
{
if (x + p.x > Width())
{
return SplitLabel(text, pFont, txt, x, y, lineheight);
}
}
//
// Wrap
//
if (x + p.x >= Width())
{
CreateNewline(x, y, lineheight);
}
Gwen::Controls::Label* pLabel = new Gwen::Controls::Label(this);
pLabel->SetText(x == 0 ? Gwen::Utility::Strings::TrimLeft<Gwen::UnicodeString>(text, L" ") : text);
pLabel->SetTextColor(txt.color);
pLabel->SetFont(pFont);
pLabel->SizeToContents();
pLabel->SetPos(x, y);
//lineheight = (lineheight + pLabel->Height()) / 2;
x += pLabel->Width();
if (x >= Width())
{
CreateNewline(x, y, lineheight);
}
}
void RichLabel::CreateNewline(int& x, int& y, int& lineheight)
{
x = 0;
y += lineheight;
}
void RichLabel::Rebuild()
{
RemoveAllChildren();
int x = 0;
int y = 0;
int lineheight = -1;
for (DividedText::List::iterator it = m_TextBlocks.begin(); it != m_TextBlocks.end(); ++it)
{
if (it->type == Type_Newline)
{
CreateNewline(x, y, lineheight);
continue;
}
if (it->type == Type_Text)
{
CreateLabel((*it).text, *it, x, y, lineheight, false);
continue;
}
}
m_bNeedsRebuild = false;
}
void RichLabel::OnBoundsChanged(Gwen::Rect oldBounds)
{
BaseClass::OnBoundsChanged(oldBounds);
Rebuild();
}
void RichLabel::Layout(Gwen::Skin::Base* skin)
{
BaseClass::Layout(skin);
if (m_bNeedsRebuild)
{
Rebuild();
}
}

View file

@ -0,0 +1,59 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_RICHLABEL_H
#define GWEN_CONTROLS_RICHLABEL_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Text.h"
#include "Gwen/TextObject.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT RichLabel : public Controls::Base
{
public:
GWEN_CONTROL(RichLabel, Gwen::Controls::Base);
void AddLineBreak();
void AddText(const Gwen::TextObject& text, Gwen::Color color, Gwen::Font* font = NULL);
virtual bool SizeToChildren(bool w = true, bool h = true);
protected:
struct DividedText
{
typedef std::list<DividedText> List;
DividedText()
{
type = 0;
font = NULL;
}
unsigned char type;
Gwen::UnicodeString text;
Gwen::Color color;
Gwen::Font* font;
};
void Layout(Gwen::Skin::Base* skin);
void SplitLabel(const Gwen::UnicodeString& text, Gwen::Font* pFont, const DividedText& txt, int& x, int& y, int& lineheight);
void CreateNewline(int& x, int& y, int& lineheight);
void CreateLabel(const Gwen::UnicodeString& text, const DividedText& txt, int& x, int& y, int& lineheight, bool NoSplit);
void Rebuild();
void OnBoundsChanged(Gwen::Rect oldBounds);
DividedText::List m_TextBlocks;
bool m_bNeedsRebuild;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,74 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ScrollBar.h"
#include "Gwen/Controls/ScrollBarButton.h"
#include "Gwen/Controls/ScrollBarBar.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(BaseScrollBar)
{
for (int i = 0; i < 2; i++)
{
m_ScrollButton[i] = new ScrollBarButton(this);
}
m_Bar = new ScrollBarBar(this);
SetBounds(0, 0, 15, 15);
m_bDepressed = false;
m_fScrolledAmount = 0;
m_fContentSize = 0;
m_fViewableContentSize = 0;
SetNudgeAmount(20);
}
void BaseScrollBar::Render(Skin::Base* skin)
{
skin->DrawScrollBar(this, false, m_bDepressed);
}
void BaseScrollBar::OnBarMoved(Controls::Base* /*control*/)
{
onBarMoved.Call(this);
}
void BaseScrollBar::BarMovedNotification()
{
OnBarMoved(this);
}
void BaseScrollBar::SetContentSize(float size)
{
if (m_fContentSize != size)
{
Invalidate();
}
m_fContentSize = size;
}
void BaseScrollBar::SetViewableContentSize(float size)
{
if (m_fViewableContentSize != size)
Invalidate();
m_fViewableContentSize = size;
}
bool BaseScrollBar::SetScrolledAmount(float amount, bool /*forceUpdate*/)
{
if (m_fScrolledAmount == amount) return false;
m_fScrolledAmount = amount;
Invalidate();
BarMovedNotification();
return true;
}

View file

@ -0,0 +1,83 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_SCROLLBAR_H
#define GWEN_CONTROLS_SCROLLBAR_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/ScrollBarBar.h"
#include "Gwen/Controls/ScrollBarButton.h"
#include "Gwen/Gwen.h"
#define SCROLL_BUTTON_UP 0
#define SCROLL_BUTTON_LEFT 0
#define SCROLL_BUTTON_DOWN 1
#define SCROLL_BUTTON_RIGHT 1
#define NUDGE_DIST 10
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT BaseScrollBar : public Base
{
public:
GWEN_CONTROL(BaseScrollBar, Base);
virtual void Render(Skin::Base* skin);
virtual void SetBarSize(int size) = 0;
virtual int GetBarSize() = 0;
virtual int GetBarPos() = 0;
virtual void OnBarMoved(Controls::Base* control);
virtual void OnMouseClickLeft(int /*x*/, int /*y*/, bool /*bDown*/) {}
virtual void ScrollToLeft() {}
virtual void ScrollToRight() {}
virtual void ScrollToTop() {}
virtual void ScrollToBottom() {}
virtual float GetNudgeAmount() { return m_fNudgeAmount / m_fContentSize; }
virtual void SetNudgeAmount(float nudge) { m_fNudgeAmount = nudge; }
virtual void BarMovedNotification();
virtual float CalculateScrolledAmount() { return 0; }
virtual int CalculateBarSize() { return 0; }
virtual bool SetScrolledAmount(float amount, bool forceUpdate);
virtual void SetContentSize(float size);
virtual void SetViewableContentSize(float size);
virtual int GetButtonSize() { return 0; }
virtual float GetScrolledAmount() { return m_fScrolledAmount; }
Gwen::Event::Caller onBarMoved;
float getContentSize()
{
return m_fContentSize;
}
float getViewableContentSize() const
{
return m_fViewableContentSize;
}
protected:
ControlsInternal::ScrollBarButton* m_ScrollButton[2];
ControlsInternal::ScrollBarBar* m_Bar;
bool m_bDepressed;
float m_fScrolledAmount;
float m_fContentSize;
float m_fViewableContentSize;
float m_fNudgeAmount;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,56 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ScrollBar.h"
#include "Gwen/Controls/ScrollBarBar.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
//Actual bar representing height of parent
GWEN_CONTROL_CONSTRUCTOR(ScrollBarBar)
{
RestrictToParent(true);
SetTarget(this);
}
void ScrollBarBar::Render(Skin::Base* skin)
{
skin->DrawScrollBarBar(this, m_bDepressed, IsHovered(), m_bHorizontal);
BaseClass::Render(skin);
}
void ScrollBarBar::OnMouseMoved(int x, int y, int deltaX, int deltaY)
{
BaseClass::OnMouseMoved(x, y, deltaX, deltaY);
if (!m_bDepressed)
return;
InvalidateParent();
}
void ScrollBarBar::OnMouseClickLeft(int x, int y, bool bDown)
{
BaseClass::OnMouseClickLeft(x, y, bDown);
InvalidateParent();
}
void ScrollBarBar::Layout(Skin::Base* /*skin*/)
{
if (!GetParent())
return;
//Move to our current position to force clamping - is this a hack?
MoveTo(X(), Y());
}
void ScrollBarBar::MoveTo(int x, int y)
{
BaseClass::MoveTo(x, y);
}

View file

@ -0,0 +1,43 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_SCROLLBARBAR_H
#define GWEN_CONTROLS_SCROLLBARBAR_H
#include "Gwen/Controls/Dragger.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT ScrollBarBar : public ControlsInternal::Dragger
{
public:
GWEN_CONTROL(ScrollBarBar, ControlsInternal::Dragger);
virtual void Render(Skin::Base* skin);
virtual void Layout(Skin::Base* skin);
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);
virtual void OnMouseClickLeft(int x, int y, bool bDown);
virtual void MoveTo(int x, int y);
virtual void SetHorizontal() { m_bHorizontal = true; }
virtual void SetVertical() { m_bHorizontal = false; }
virtual bool IsVertical() { return !m_bHorizontal; }
virtual bool IsHorizontal() { return m_bHorizontal; }
virtual bool IsDepressed() { return m_bDepressed; }
protected:
bool m_bHorizontal;
};
} // namespace ControlsInternal
} // namespace Gwen
#endif

View file

@ -0,0 +1,43 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ScrollBar.h"
#include "Gwen/Controls/ScrollBarButton.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(ScrollBarButton)
{
m_iDirection = 0;
SetBounds(0, 0, 0, 0);
}
void ScrollBarButton::SetDirectionUp()
{
m_iDirection = Pos::Top;
}
void ScrollBarButton::SetDirectionDown()
{
m_iDirection = Pos::Bottom;
}
void ScrollBarButton::SetDirectionLeft()
{
m_iDirection = Pos::Left;
}
void ScrollBarButton::SetDirectionRight()
{
m_iDirection = Pos::Right;
}
void ScrollBarButton::Render(Skin::Base* skin)
{
skin->DrawScrollButton(this, m_iDirection, m_bDepressed);
}

View file

@ -0,0 +1,34 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_SCROLLBARBOTTON_H
#define GWEN_CONTROLS_SCROLLBARBOTTON_H
#include "Gwen/Controls/Button.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT ScrollBarButton : public Controls::Button
{
public:
GWEN_CONTROL(ScrollBarButton, Controls::Button);
void Render(Skin::Base* skin);
void SetDirectionUp();
void SetDirectionDown();
void SetDirectionLeft();
void SetDirectionRight();
protected:
int m_iDirection;
};
} // namespace ControlsInternal
} // namespace Gwen
#endif

View file

@ -0,0 +1,244 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/ScrollControl.h"
#include "Gwen/Controls/ScrollBar.h"
#include "Gwen/Controls/VerticalScrollBar.h"
#include "Gwen/Controls/HorizontalScrollBar.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(ScrollControl)
{
SetMouseInputEnabled(false);
m_VerticalScrollBar = new VerticalScrollBar(this);
m_VerticalScrollBar->Dock(Pos::Right);
m_VerticalScrollBar->onBarMoved.Add(this, &ScrollControl::VBarMoved);
m_VerticalScrollBar->SetNudgeAmount(30);
m_bCanScrollV = true;
m_HorizontalScrollBar = new HorizontalScrollBar(this);
m_HorizontalScrollBar->Dock(Pos::Bottom);
m_HorizontalScrollBar->onBarMoved.Add(this, &ScrollControl::HBarMoved);
m_bCanScrollH = true;
m_HorizontalScrollBar->SetNudgeAmount(30);
m_InnerPanel = new Base(this);
m_InnerPanel->SetPos(0, 0);
m_InnerPanel->SetMargin(Margin(5, 5, 5, 5));
m_InnerPanel->SendToBack();
m_InnerPanel->SetMouseInputEnabled(false);
m_bAutoHideBars = false;
}
void ScrollControl::SetScroll(bool h, bool v)
{
m_bCanScrollV = v;
m_bCanScrollH = h;
m_VerticalScrollBar->SetHidden(!m_bCanScrollV);
m_HorizontalScrollBar->SetHidden(!m_bCanScrollH);
}
void ScrollControl::SetInnerSize(int w, int h)
{
m_InnerPanel->SetSize(w, h);
}
void ScrollControl::VBarMoved(Controls::Base* /*control*/)
{
Invalidate();
}
void ScrollControl::HBarMoved(Controls::Base* /*control*/)
{
Invalidate();
}
void ScrollControl::OnChildBoundsChanged(Gwen::Rect /*oldChildBounds*/, Base* /*pChild*/)
{
UpdateScrollBars();
}
void ScrollControl::Layout(Skin::Base* skin)
{
UpdateScrollBars();
BaseClass::Layout(skin);
}
bool ScrollControl::OnMouseWheeled(int iDelta)
{
if (CanScrollV() && m_VerticalScrollBar->Visible())
{
if (m_VerticalScrollBar->SetScrolledAmount(m_VerticalScrollBar->GetScrolledAmount() - m_VerticalScrollBar->GetNudgeAmount() * ((float)iDelta / 60.0f), true))
return true;
}
if (CanScrollH() && m_HorizontalScrollBar->Visible())
{
if (m_HorizontalScrollBar->SetScrolledAmount(m_HorizontalScrollBar->GetScrolledAmount() - m_HorizontalScrollBar->GetNudgeAmount() * ((float)iDelta / 60.0f), true))
return true;
}
return false;
}
void ScrollControl::Render(Skin::Base* skin)
{
#if 0
// Debug render - this shouldn't render ANYTHING REALLY - it should be up to the parent!
Gwen::Rect rect = GetRenderBounds();
Gwen::Renderer::Base* render = skin->GetRender();
render->SetDrawColor( Gwen::Color( 255, 255, 0, 100 ) );
render->DrawFilledRect( rect );
render->SetDrawColor( Gwen::Color( 255, 0, 0, 100 ) );
render->DrawFilledRect( m_InnerPanel->GetBounds() );
render->RenderText( skin->GetDefaultFont(), Gwen::Point( 0, 0 ), Utility::Format( L"Offset: %i %i", m_InnerPanel->X(), m_InnerPanel->Y() ) );
#else //0
(void)skin;
#endif //0
}
void ScrollControl::UpdateScrollBars()
{
if (!m_InnerPanel)
return;
int childrenWidth = 0;
int childrenHeight = 0;
//Get the max size of all our children together
for (Base::List::iterator iter = m_InnerPanel->Children.begin(); iter != m_InnerPanel->Children.end(); ++iter)
{
Base* pChild = *iter;
childrenWidth = Utility::Max(childrenWidth, pChild->Right());
childrenHeight = Utility::Max(childrenHeight, pChild->Bottom());
}
m_InnerPanel->SetSize(Utility::Max(Width(), childrenWidth), Utility::Max(Height(), childrenHeight));
float hg = (float)(childrenWidth + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()));
if (hg == 0.f)
hg = 0.00001f;
float wPercent = (float)Width() / hg;
hg = (float)(childrenHeight + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height()));
if (hg == 0.f)
hg = 0.00001f;
float hPercent = (float)Height() / hg;
if (m_bCanScrollV)
SetVScrollRequired(hPercent >= 1);
else
m_VerticalScrollBar->SetHidden(true);
if (m_bCanScrollH)
SetHScrollRequired(wPercent >= 1);
else
m_HorizontalScrollBar->SetHidden(true);
m_VerticalScrollBar->SetContentSize(m_InnerPanel->Height());
m_VerticalScrollBar->SetViewableContentSize(Height() - (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height()));
m_HorizontalScrollBar->SetContentSize(m_InnerPanel->Width());
m_HorizontalScrollBar->SetViewableContentSize(Width() - (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()));
int newInnerPanelPosX = 0;
int newInnerPanelPosY = 0;
if (CanScrollV() && !m_VerticalScrollBar->Hidden())
{
newInnerPanelPosY = -((m_InnerPanel->Height()) - Height() + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height())) * m_VerticalScrollBar->GetScrolledAmount();
}
if (CanScrollH() && !m_HorizontalScrollBar->Hidden())
{
newInnerPanelPosX = -((m_InnerPanel->Width()) - Width() + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width())) * m_HorizontalScrollBar->GetScrolledAmount();
}
m_InnerPanel->SetPos(newInnerPanelPosX, newInnerPanelPosY);
}
void ScrollControl::SetVScrollRequired(bool req)
{
if (req)
{
m_VerticalScrollBar->SetScrolledAmount(0, true);
m_VerticalScrollBar->SetDisabled(true);
if (m_bAutoHideBars)
m_VerticalScrollBar->SetHidden(true);
}
else
{
m_VerticalScrollBar->SetHidden(false);
m_VerticalScrollBar->SetDisabled(false);
}
}
void ScrollControl::SetHScrollRequired(bool req)
{
if (req)
{
m_HorizontalScrollBar->SetScrolledAmount(0, true);
m_HorizontalScrollBar->SetDisabled(true);
if (m_bAutoHideBars)
m_HorizontalScrollBar->SetHidden(true);
}
else
{
m_HorizontalScrollBar->SetHidden(false);
m_HorizontalScrollBar->SetDisabled(true);
}
}
void ScrollControl::ScrollToBottom()
{
if (CanScrollV())
{
UpdateScrollBars();
m_VerticalScrollBar->ScrollToBottom();
}
}
void ScrollControl::ScrollToTop()
{
if (CanScrollV())
{
UpdateScrollBars();
m_VerticalScrollBar->ScrollToTop();
}
}
void ScrollControl::ScrollToLeft()
{
if (CanScrollH())
{
UpdateScrollBars();
m_HorizontalScrollBar->ScrollToLeft();
}
}
void ScrollControl::ScrollToRight()
{
if (CanScrollH())
{
UpdateScrollBars();
m_HorizontalScrollBar->ScrollToRight();
}
}
void ScrollControl::Clear()
{
m_InnerPanel->RemoveAllChildren();
}

View file

@ -0,0 +1,67 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_SCROLLCONTROL_H
#define GWEN_CONTROLS_SCROLLCONTROL_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/ScrollBar.h"
#include "Gwen/Controls/VerticalScrollBar.h"
#include "Gwen/Controls/HorizontalScrollBar.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT ScrollControl : public Base
{
public:
GWEN_CONTROL(ScrollControl, Base);
virtual void Layout(Skin::Base* skin);
virtual void Render(Skin::Base* skin);
virtual void SetScroll(bool h, bool v);
virtual void SetAutoHideBars(bool should) { m_bAutoHideBars = should; }
virtual bool CanScrollH() { return m_bCanScrollH; }
virtual bool CanScrollV() { return m_bCanScrollV; }
virtual void OnChildBoundsChanged(Gwen::Rect oldChildBounds, Base* pChild);
virtual void UpdateScrollBars();
virtual void SetVScrollRequired(bool req);
virtual void SetHScrollRequired(bool req);
virtual void SetInnerSize(int w, int h);
virtual void VBarMoved(Controls::Base* control);
virtual void HBarMoved(Controls::Base* control);
virtual bool OnMouseWheeled(int iDelta);
virtual void ScrollToBottom();
virtual void ScrollToTop();
virtual void ScrollToLeft();
virtual void ScrollToRight();
virtual void Clear();
protected:
bool m_bCanScrollH;
bool m_bCanScrollV;
bool m_bAutoHideBars;
public:
Controls::BaseScrollBar* m_VerticalScrollBar;
Controls::BaseScrollBar* m_HorizontalScrollBar;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,102 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include <math.h>
#include <cmath>
#include "Gwen/Controls/Slider.h"
using namespace Gwen;
using namespace Gwen::Controls;
using namespace Gwen::ControlsInternal;
GWEN_CONTROL_CONSTRUCTOR(SliderBar)
{
SetTarget(this);
RestrictToParent(true);
}
void SliderBar::Render(Skin::Base* skin)
{
skin->DrawButton(this, m_bDepressed, IsHovered());
}
Slider::Slider(Controls::Base* pParent) : BaseClass(pParent)
{
SetBounds(Gwen::Rect(0, 0, 32, 128));
m_SliderBar = new SliderBar(this);
m_SliderBar->onDragged.Add(this, &Slider::OnMoved);
m_fMin = 0.0f;
m_fMax = 1.0f;
m_bClampToNotches = false;
m_iNumNotches = 5;
m_fValue = 0.0f;
SetTabable(true);
}
void Slider::OnMoved(Controls::Base* /*control*/)
{
SetValueInternal(CalculateValue());
}
void Slider::Layout(Skin::Base* skin)
{
BaseClass::Layout(skin);
}
float Slider::CalculateValue()
{
return 0;
}
void Slider::SetValue(float val, bool /*forceUpdate*/)
{
if (val < m_fMin) val = m_fMin;
if (val > m_fMax) val = m_fMax;
// Normalize Value
val = (val - m_fMin) / (m_fMax - m_fMin);
SetValueInternal(val);
Redraw();
}
void Slider::SetValueInternal(float val)
{
if (m_bClampToNotches)
{
val = std::floor((val * (float)m_iNumNotches) + 0.5f);
val /= (float)m_iNumNotches;
}
if (m_fValue != val)
{
m_fValue = val;
onValueChanged.Call(this);
}
UpdateBarFromValue();
}
float Slider::GetValue()
{
return m_fMin + (m_fValue * (m_fMax - m_fMin));
}
void Slider::SetRange(float fMin, float fMax)
{
m_fMin = fMin;
m_fMax = fMax;
}
void Slider::RenderFocus(Gwen::Skin::Base* skin)
{
if (Gwen::KeyboardFocus != this) return;
if (!IsTabable()) return;
skin->DrawKeyboardHighlight(this, GetRenderBounds(), 0);
}

View file

@ -0,0 +1,100 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_SLIDER_H
#define GWEN_CONTROLS_SLIDER_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/Dragger.h"
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace ControlsInternal
{
class GWEN_EXPORT SliderBar : public ControlsInternal::Dragger
{
GWEN_CONTROL(SliderBar, ControlsInternal::Dragger);
virtual void Render(Skin::Base* skin);
};
} // namespace ControlsInternal
namespace Controls
{
class GWEN_EXPORT Slider : public Base
{
GWEN_CONTROL(Slider, Base);
virtual void Render(Skin::Base* skin) = 0;
virtual void Layout(Skin::Base* skin);
virtual void SetClampToNotches(bool bClamp) { m_bClampToNotches = bClamp; }
virtual void SetNotchCount(int num) { m_iNumNotches = num; }
virtual int GetNotchCount() { return m_iNumNotches; }
virtual void SetRange(float fMin, float fMax);
virtual float GetRangeMin() const
{
return m_fMin;
}
virtual float GetRangeMax() const
{
return m_fMax;
}
virtual float GetValue();
virtual void SetValue(float val, bool forceUpdate = true);
virtual float CalculateValue();
virtual void OnMoved(Controls::Base* control);
virtual void OnMouseClickLeft(int /*x*/, int /*y*/, bool /*bDown*/){};
virtual bool OnKeyRight(bool bDown)
{
if (bDown) SetValue(GetValue() + 1, true);
return true;
}
virtual bool OnKeyLeft(bool bDown)
{
if (bDown) SetValue(GetValue() - 1, true);
return true;
}
virtual bool OnKeyUp(bool bDown)
{
if (bDown) SetValue(GetValue() + 1, true);
return true;
}
virtual bool OnKeyDown(bool bDown)
{
if (bDown) SetValue(GetValue() - 1, true);
return true;
}
virtual void RenderFocus(Gwen::Skin::Base* skin);
Gwen::Event::Caller onValueChanged;
protected:
virtual void SetValueInternal(float fVal);
virtual void UpdateBarFromValue() = 0;
ControlsInternal::SliderBar* m_SliderBar;
bool m_bClampToNotches;
int m_iNumNotches;
float m_fValue;
float m_fMin;
float m_fMax;
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,23 @@
#include "Gwen/Gwen.h"
#include "Gwen/Controls/SplitterBar.h"
using namespace Gwen;
using namespace Controls;
GWEN_CONTROL_CONSTRUCTOR(SplitterBar)
{
SetTarget(this);
RestrictToParent(true);
}
void SplitterBar::Render(Skin::Base* skin)
{
if (ShouldDrawBackground())
skin->DrawButton(this, true, false);
}
void SplitterBar::Layout(Skin::Base* /*skin*/)
{
MoveTo(X(), Y());
}

View file

@ -0,0 +1,23 @@
#pragma once
#ifndef GWEN_CONTROLS_SPLITTERBAR_H
#define GWEN_CONTROLS_SPLITTERBAR_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Dragger.h"
namespace Gwen
{
namespace Controls
{
class GWEN_EXPORT SplitterBar : public ControlsInternal::Dragger
{
public:
GWEN_CONTROL(SplitterBar, ControlsInternal::Dragger);
void Render(Skin::Base* skin);
void Layout(Skin::Base* skin);
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,35 @@
#pragma once
#ifndef GWEN_CONTROLS_STATUSBAR_H
#define GWEN_CONTROLS_STATUSBAR_H
#include "Gwen/Gwen.h"
#include "Gwen/Controls/Base.h"
namespace Gwen
{
namespace Controls
{
class StatusBar : public Controls::Base
{
public:
GWEN_CONTROL_INLINE(StatusBar, Controls::Base)
{
SetBounds(0, 0, 200, 22);
Dock(Pos::Bottom);
SetPadding(Padding(2, 2, 2, 2));
}
virtual void AddControl(Controls::Base* pCtrl, bool bRight)
{
pCtrl->SetParent(this);
pCtrl->Dock(bRight ? Pos::Right : Pos::Left);
}
virtual void Render(Skin::Base* skin)
{
skin->DrawStatusBar(this);
}
};
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,48 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_SYMBOL_H
#define GWEN_CONTROLS_SYMBOL_H
#include "Gwen/BaseRender.h"
#include "Gwen/Controls/Base.h"
#include "Gwen/Skin.h"
namespace Gwen
{
namespace Controls
{
namespace Symbol
{
class GWEN_EXPORT Base : public Controls::Base
{
public:
GWEN_CONTROL_INLINE(Base, Controls::Base)
{
SetMouseInputEnabled(false);
}
};
class GWEN_EXPORT Arrow : public Base
{
public:
Arrow(Gwen::Controls::Base* pnl) : Base(pnl)
{
}
virtual void Render(Gwen::Skin::Base* pSkin)
{
Gwen::Rect r(Width() / 2 - 2, Height() / 2 - 2, 5, 5);
pSkin->DrawArrowRight(r);
}
};
} // namespace Symbol
} // namespace Controls
} // namespace Gwen
#endif

View file

@ -0,0 +1,91 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Gwen.h"
#include "Gwen/Skin.h"
#include "Gwen/Controls/TabButton.h"
#include "Gwen/Controls/TabControl.h"
#include "Gwen/Controls/Highlight.h"
#include "Gwen/DragAndDrop.h"
using namespace Gwen;
using namespace Gwen::Controls;
GWEN_CONTROL_CONSTRUCTOR(TabButton)
{
m_Page = NULL;
m_Control = NULL;
SetPadding(Padding(2, 2, 2, 2));
DragAndDrop_SetPackage(true, "TabButtonMove");
SetAlignment(Pos::Top | Pos::Left);
SetTextPadding(Padding(5, 3, 3, 3));
}
void TabButton::Render(Skin::Base* skin)
{
skin->DrawTabButton(this, m_Page && m_Page->Visible());
}
void TabButton::SetTabControl(TabControl* ctrl)
{
if (m_Control == ctrl) return;
if (m_Control)
{
m_Control->OnLoseTab(this);
}
m_Control = ctrl;
}
bool TabButton::DragAndDrop_ShouldStartDrag()
{
return m_Control->DoesAllowDrag();
}
bool TabButton::OnKeyUp(bool bDown)
{
OnKeyLeft(bDown);
return true;
}
bool TabButton::OnKeyDown(bool bDown)
{
OnKeyRight(bDown);
return true;
}
bool TabButton::OnKeyLeft(bool bDown)
{
if (bDown)
{
Base::List::reverse_iterator it = std::find(m_Parent->Children.rbegin(), m_Parent->Children.rend(), this);
if (it != m_Parent->Children.rend() && (++it != m_Parent->Children.rend()))
{
Base* pNextTab = *it;
GetTabControl()->OnTabPressed(pNextTab);
Gwen::KeyboardFocus = pNextTab;
}
}
return true;
}
bool TabButton::OnKeyRight(bool bDown)
{
if (bDown)
{
Base::List::iterator it = std::find(m_Parent->Children.begin(), m_Parent->Children.end(), this);
if (it != m_Parent->Children.end() && (++it != m_Parent->Children.end()))
{
Base* pNextTab = *it;
GetTabControl()->OnTabPressed(pNextTab);
Gwen::KeyboardFocus = pNextTab;
}
}
return true;
}

View file

@ -0,0 +1,50 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#ifndef GWEN_CONTROLS_TABBUTTON_H
#define GWEN_CONTROLS_TABBUTTON_H
#include "Gwen/Controls/Base.h"
#include "Gwen/Controls/Button.h"
namespace Gwen
{
namespace Controls
{
class TabControl;
class GWEN_EXPORT TabButton : public Button
{
public:
GWEN_CONTROL(TabButton, Button);
virtual void Render(Skin::Base* skin);
void SetPage(Base* page) { m_Page = page; }
Base* GetPage() { return m_Page; }
void SetTabControl(TabControl* ctrl);
TabControl* GetTabControl() { return m_Control; }
bool IsActive() { return m_Page && m_Page->Visible(); }
virtual bool DragAndDrop_ShouldStartDrag();
virtual void DragAndDrop_StartDragging(Gwen::DragAndDrop::Package* /*pPackage*/, int /*x*/, int /*y*/) { SetHidden(true); }
virtual void DragAndDrop_EndDragging(bool /*bSuccess*/, int /*x*/, int /*y*/) { SetHidden(false); }
virtual bool OnKeyLeft(bool bDown);
virtual bool OnKeyRight(bool bDown);
virtual bool OnKeyUp(bool bDown);
virtual bool OnKeyDown(bool bDown);
private:
Base* m_Page;
TabControl* m_Control;
};
} // namespace Controls
} // namespace Gwen
#endif

Some files were not shown because too many files have changed in this diff Show more