/* 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 #include #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 List; typedef std::map 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 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