reorganize files and add btgui

This commit is contained in:
erwin coumans 2013-03-12 23:52:31 -07:00
parent 9612c2cd3d
commit e4a7b6f487
262 changed files with 46553 additions and 14753 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

21738
btgui/FontFiles/OpenSans.cpp Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

79
btgui/Gwen/Align.h Normal file
View File

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

142
btgui/Gwen/Anim.cpp Normal file
View File

@ -0,0 +1,142 @@
/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Anim.h"
#include "Gwen/Utility.h"
#include <math.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( pow( fDelta, m_fEase ) );
if ( fDelta == 1.0f )
{
m_bFinished = true;
OnFinish();
}
}
bool Gwen::Anim::TimedAnimation::Finished()
{
return m_bFinished;
}
#endif

130
btgui/Gwen/Anim.h Normal file
View File

@ -0,0 +1,130 @@
/*
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 Tools
{
class Remove : public TimedAnimation
{
public:
Remove( float fDelay = 0.0f ) : TimedAnimation( 0.0f, fDelay ){}
virtual void OnFinish(){ m_Control->DelayedDelete(); }
};
}
}
}
#endif
#endif

221
btgui/Gwen/BaseRender.cpp Normal file
View File

@ -0,0 +1,221 @@
/*
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>
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 = ceil( ((float) x ) * m_fScale );
y = ceil( ((float) y ) * m_fScale );
}
void Base::Translate( Gwen::Rect& rect )
{
Translate( rect.x, rect.y );
rect.w = ceil(((float) rect.w ) * m_fScale);
rect.h = 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;
}
}
}

119
btgui/Gwen/BaseRender.h Normal file
View File

@ -0,0 +1,119 @@
/*
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 );
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;
ICacheToTexture* m_RTT;
public:
void SetScale( float fScale ){ m_fScale = fScale; }
float Scale() const { return m_fScale; }
float m_fScale;
};
}
}
#endif

16
btgui/Gwen/Config.h Normal file
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

10
btgui/Gwen/Controls.h Normal file
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

1082
btgui/Gwen/Controls/Base.cpp Normal file

File diff suppressed because it is too large Load Diff

507
btgui/Gwen/Controls/Base.h Normal file
View File

@ -0,0 +1,507 @@
/*
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 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
};
}
}
// 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,169 @@
/*
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,79 @@
/*
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 );
public:
Gwen::Event::Caller onPress;
Gwen::Event::Caller onDown;
Gwen::Event::Caller onUp;
Gwen::Event::Caller onDoubleClick;
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;
};
}
}
#endif

View File

@ -0,0 +1,233 @@
/*
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 )
{
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,107 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,57 @@
/*
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,82 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,326 @@
/*
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,61 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,222 @@
/*
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 );
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,89 @@
/*
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 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;
};
}
}
#endif

View File

@ -0,0 +1,204 @@
/*
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::reverse_iterator it = std::find( m_Menu->Children.rbegin(), m_Menu->Children.rend(), m_SelectedItem );
if ( it != m_Menu->Children.rend() && ( ++it != m_Menu->Children.rend() ) )
{
Base* pUpElement = *it;
OnItemSelected(pUpElement);
}
}
return true;
}
bool ComboBox::OnKeyDown( bool bDown )
{
if ( bDown )
{
Base::List::iterator it = std::find( m_Menu->Children.begin(), m_Menu->Children.end(), m_SelectedItem );
if ( it != m_Menu->Children.end() && ( ++it != m_Menu->Children.end() ) )
{
Base* pDownElement = *it;
OnItemSelected(pDownElement);
}
}
return true;
}
void ComboBox::RenderFocus( Gwen::Skin::Base* /*skin*/ )
{
}

View File

@ -0,0 +1,87 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,183 @@
#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[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,63 @@
#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;
char m_iZoomedSection;
Gwen::Event::Caller onZoomed;
Gwen::Event::Caller onUnZoomed;
Gwen::Event::Caller onZoomChange;
};
}
}
#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,12 @@
/*
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,35 @@
#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 );
}
}
}
#endif

View File

@ -0,0 +1,40 @@
#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 );
}
}
}
#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
}
}
#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,77 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,92 @@
/*
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,42 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,59 @@
/*
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,43 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,42 @@
/*
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,34 @@
/*
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 );
};
}
}
#endif

View File

@ -0,0 +1,172 @@
/*
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,47 @@
/*
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;
};
}
}
#endif

View File

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

View File

@ -0,0 +1,136 @@
/*
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,49 @@
/*
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);
};
}
}
#endif

View File

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

View File

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

View File

@ -0,0 +1,78 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,75 @@
/*
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,70 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,25 @@
/*
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,29 @@
/*
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 );
};
}
}
#endif

View File

@ -0,0 +1,83 @@
/*
GWEN
Copyright (c) 2011 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#pragma once
#include "Gwen/Controls/Base.h"
namespace Gwen
{
namespace Controls
{
namespace Layout
{
class 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];
};
}
}
}

View File

@ -0,0 +1,87 @@
/*
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];
};
}
}
}
#endif

View File

@ -0,0 +1,87 @@
/*
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];
};
}
}
}
#endif

View File

@ -0,0 +1,264 @@
/*
GWEN
Copyright (c) 2011 Facepunch Studios
See license in Gwen.h
*/
#pragma once
#pragma once
#include "Gwen/Controls/Label.h"
namespace Gwen
{
namespace Controls
{
namespace Layout
{
class Table;
class 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;
}
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]->SetTextPadding( Gwen::Rect( 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 = 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 ) {}
private:
int m_ColumnCount;
Label* m_Columns[MaxColumns];
friend class Table;
};
class 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 + rand()%100;
}
m_bSizeToContents = false;
}
void SetColumnCount( int i )
{
if ( m_iColumnCount == i ) return;
for ( Base::List::iterator it = m_Children.begin(); it != m_Children.end(); ++it )
{
Base* el = *it;
if (el->getType()!=TypeTableRow)
continue;
TableRow* pRow = static_cast<TableRow*>(*it);
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 Layout( Skin::Base* skin )
{
Debug::Msg( "TABLE LAYOUT\n" );
BaseClass::Layout( skin );
if ( m_bSizeToContents )
{
DoSizeToContents();
m_bSizeToContents = false;
}
for ( Base::List::iterator it = m_Children.begin(); it != m_Children.end(); ++it )
{
TableRow* pRow = static_cast<TableRow*>(*it);
if ( !pRow ) continue;
for (int i=0; i<TableRow::MaxColumns && i < m_iColumnCount; i++)
{
pRow->SetColumnWidth( i, m_ColumnWidth[i] );
}
}
}
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 = m_Children.begin(); it != m_Children.end(); ++it )
{
TableRow* pRow = static_cast<TableRow*>(*it);
if ( !pRow ) continue;
pRow->SizeToContents();
for (int i=0; i<TableRow::MaxColumns; i++)
{
if ( pRow->m_Columns[i] )
{
m_ColumnWidth[i] = max( m_ColumnWidth[i], pRow->m_Columns[i]->Width() );
}
}
}
Invalidate();
}
private:
bool m_bSizeToContents;
int m_iColumnCount;
int m_iDefaultRowHeight;
int m_ColumnWidth[ TableRow::MaxColumns ];
};
}
}
}

View File

@ -0,0 +1,294 @@
/*
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;
}
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 )
{
TableRow* pRow = static_cast<TableRow*>(*it);
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 )
{
TableRow* pRow = static_cast<TableRow*>(*it);
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 )
{
TableRow* pRow = static_cast<TableRow*>(*it);
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 )
{
TableRow* pRow = static_cast<TableRow*>(*it);
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 ];
};
}
}
}
#endif

View File

@ -0,0 +1,317 @@
/*
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 ];
};
}
}
}
#endif

View File

@ -0,0 +1,143 @@
/*
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,67 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,172 @@
/*
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,86 @@
/*
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 );
};
}
}
#endif

View File

@ -0,0 +1,137 @@
/*
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,69 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,44 @@
/*
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,39 @@
/*
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() {}
};
}
}
#endif

View File

@ -0,0 +1,37 @@
#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 );
}
};
}
}
#endif

View File

@ -0,0 +1,117 @@
/*
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,75 @@
/*
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;
};
}
}
#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,46 @@
#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;
};
}
}
#endif

View File

@ -0,0 +1,49 @@
/*
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,45 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,125 @@
/*
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,77 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,60 @@
/*
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;
};
}
}
}
#endif

View File

@ -0,0 +1,80 @@
#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;
};
}
}
}
#endif

View File

@ -0,0 +1,52 @@
/*
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;
};
}
}
}
#endif

View File

@ -0,0 +1,62 @@
/*
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;
}
};
}
}
#endif

View File

@ -0,0 +1,24 @@
/*
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,78 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,74 @@
/*
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,48 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,110 @@
/*
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,55 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,120 @@
/*
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,39 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,209 @@
/*
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,62 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,83 @@
/*
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,77 @@
/*
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;
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;
};
}
}
#endif

View File

@ -0,0 +1,57 @@
/*
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,46 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,45 @@
/*
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,36 @@
/*
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;
};
}
}
#endif

View File

@ -0,0 +1,242 @@
/*
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 wPercent = (float)Width() / (float)(childrenWidth + (m_VerticalScrollBar->Hidden() ? 0 : m_VerticalScrollBar->Width()));
float hPercent = (float)Height() / (float)(childrenHeight + (m_HorizontalScrollBar->Hidden() ? 0 : m_HorizontalScrollBar->Height()));
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();
}

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