diff --git a/Makefile b/Makefile index fff39c52b..17c5d23ec 100644 --- a/Makefile +++ b/Makefile @@ -24,12 +24,12 @@ else LINKFLAGS = endif -export CC = gcc -export CPP = g++ - ifeq ($(LLVM_BUILD), yes) export CC = llvm-gcc export CPP = llvm-g++ +else +export CC = gcc +export CPP = g++ endif export CFLAGS = -Wall $(DEBUGFLAGS) $(BUILDFLAGS) @@ -145,6 +145,9 @@ libeepp-s.a: $(FOBJHELPERS) $(FOBJMODULES) libeepp.so: $(FOBJHELPERS) $(FOBJMODULES) $(CPP) $(LDFLAGS) -Wl,-soname,$(LIB).$(VERSION) -o $(LIBNAME) $(FOBJHELPERS) $(FOBJMODULES) -lfreetype -lSDL -lsndfile -lopenal -lGL -lGLU +os: + @echo $(OS) + test: $(EXE) eeiv: $(EXEIV) diff --git a/ee.win.cbp b/ee.win.cbp index 77dd7ac60..74a0b8f00 100644 --- a/ee.win.cbp +++ b/ee.win.cbp @@ -514,12 +514,16 @@ + + + + @@ -536,8 +540,16 @@ + + + + + + + + @@ -546,6 +558,8 @@ + + @@ -562,8 +576,6 @@ - - diff --git a/src/graphics/ctexture.cpp b/src/graphics/ctexture.cpp index 946935882..539ca44c4 100755 --- a/src/graphics/ctexture.cpp +++ b/src/graphics/ctexture.cpp @@ -129,7 +129,7 @@ Uint8 * cTexture::iLock( const bool& ForceRGBA, const bool& KeepFormat ) { if ( KeepFormat && ( mFlags & TEX_FLAG_COMPRESSED ) ) { glGetCompressedTexImage( GL_TEXTURE_2D, 0, reinterpret_cast (&mPixels[0]) ); - } else { + } else { Uint32 Channel = GL_RGBA; if ( 3 == mChannels ) @@ -137,10 +137,10 @@ Uint8 * cTexture::iLock( const bool& ForceRGBA, const bool& KeepFormat ) { else if ( 2 == mChannels ) Channel = GL_LUMINANCE_ALPHA; else if ( 1 == mChannels ) - Channel = GL_ALPHA; + Channel = GL_ALPHA; glGetTexImage( GL_TEXTURE_2D, 0, Channel, GL_UNSIGNED_BYTE, reinterpret_cast (&mPixels[0]) ); - } + } if ( PreviousTexture != (GLint)mTexture ) glBindTexture(GL_TEXTURE_2D, PreviousTexture); @@ -172,7 +172,7 @@ bool cTexture::Unlock( const bool& KeepData, const bool& Modified ) { NTexId = SOIL_create_OGL_texture( reinterpret_cast(&mPixels[0]), &width, &height, mChannels, mTexture, flags ); - TextureFilter(mFilter); + iTextureFilter(mFilter); if ( PreviousTexture != (GLint)mTexture ) glBindTexture(GL_TEXTURE_2D, PreviousTexture); @@ -225,26 +225,30 @@ bool cTexture::SaveToFile( const std::string& filepath, const EE_SAVE_TYPE& Form } void cTexture::TextureFilter(const EE_TEX_FILTER& filter) { + if ( mFilter != filter ) { + iTextureFilter( filter ); + } +} + +void cTexture::iTextureFilter( const EE_TEX_FILTER& filter ) { if (mTexture) { - if ( mFilter != filter ) { - mFilter = filter; + mFilter = filter; - GLint PreviousTexture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture); + GLint PreviousTexture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture); - if ( PreviousTexture != (GLint)mTexture ) - glBindTexture(GL_TEXTURE_2D, mTexture); + if ( PreviousTexture != (GLint)mTexture ) + glBindTexture(GL_TEXTURE_2D, mTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (mFilter == TEX_FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (mFilter == TEX_FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST); - if ( mFlags & TEX_FLAG_MIPMAP ) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mFilter == TEX_FILTER_LINEAR) ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mFilter == TEX_FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST); + if ( mFlags & TEX_FLAG_MIPMAP ) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mFilter == TEX_FILTER_LINEAR) ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mFilter == TEX_FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST); - if ( PreviousTexture != (GLint)mTexture ) - glBindTexture(GL_TEXTURE_2D, PreviousTexture); - } + if ( PreviousTexture != (GLint)mTexture ) + glBindTexture(GL_TEXTURE_2D, PreviousTexture); } } @@ -358,14 +362,16 @@ void cTexture::Reload() { if ( ( mFlags & TEX_FLAG_COMPRESSED ) ) { if ( mTexture != PreviousTexture ) glBindTexture( GL_TEXTURE_2D, mTexture ); - - if ( Grabed() ) - mTexture = SOIL_create_OGL_texture( reinterpret_cast ( &mPixels[0] ), &width, &height, mChannels, mTexture, flags | SOIL_FLAG_COMPRESS_TO_DXT ); + + if ( Grabed() ) + mTexture = SOIL_create_OGL_texture( reinterpret_cast ( &mPixels[0] ), &width, &height, mChannels, mTexture, flags | SOIL_FLAG_COMPRESS_TO_DXT ); else glCompressedTexImage2D( mTexture, 0, mInternalFormat, width, height, 0, mSize, &mPixels[0] ); } else mTexture = SOIL_create_OGL_texture( reinterpret_cast ( &mPixels[0] ), &width, &height, mChannels, mTexture, flags ); + iTextureFilter( mFilter ); + if ( mTexture != PreviousTexture ) glBindTexture(GL_TEXTURE_2D, PreviousTexture); } else { @@ -373,7 +379,7 @@ void cTexture::Reload() { Reload(); Unlock(); } -} +} const Uint32& cTexture::HashName() const { return mId; diff --git a/src/graphics/ctexture.hpp b/src/graphics/ctexture.hpp index 69a040034..d6d1496b9 100755 --- a/src/graphics/ctexture.hpp +++ b/src/graphics/ctexture.hpp @@ -236,6 +236,8 @@ class EE_API cTexture : public cImage { void ApplyClampMode(); Uint8 * iLock( const bool& ForceRGBA, const bool& KeepFormat ); + + void iTextureFilter( const EE_TEX_FILTER& filter ); }; }} diff --git a/src/test/ee.cpp b/src/test/ee.cpp index 25416aed7..06019bb59 100644 --- a/src/test/ee.cpp +++ b/src/test/ee.cpp @@ -606,6 +606,7 @@ void cEETest::CreateUI() { MenuParams.Flags = UI_AUTO_SIZE | UI_AUTO_PADDING; MenuParams.Size = eeSize( 0, 200 ); MenuParams.MinWidth = 100; + MenuParams.MinSpaceForIcons = 16; MenuParams.PosSet( 0, 0 ); MenuParams.FontOverColor = eeColorA( 255, 255, 255, 255 ); Menu = eeNew( cUIPopUpMenu, ( MenuParams ) ); @@ -616,6 +617,22 @@ void cEETest::CreateUI() { Menu->Add( L"Save As..." ); Menu->Add( L"Save All" ); Menu->AddCheckBox( L"Check Me" ); + + cUIPopUpMenu * Menu3 = eeNew( cUIPopUpMenu, ( MenuParams ) ); + Menu3->Add( L"Hello World 1" ); + Menu3->Add( L"Hello World 2" ); + Menu3->Add( L"Hello World 3" ); + Menu3->Add( L"Hello World 4" ); + + cUIPopUpMenu * Menu2 = eeNew( cUIPopUpMenu, ( MenuParams ) ); + Menu2->Add( L"Test 1" ); + Menu2->Add( L"Test 2" ); + Menu2->Add( L"Test 3" ); + Menu2->Add( L"Test 4" ); + Menu2->AddSubMenu( L"Hello World", NULL, Menu3 ); + + Menu->AddSubMenu( L"Teh Menuh", NULL, Menu2 ) ; + Menu->AddSeparator(); Menu->Add( L"Quit" ); diff --git a/src/ui/cuicontrol.cpp b/src/ui/cuicontrol.cpp index f5cde5d71..f0fa7b8e8 100644 --- a/src/ui/cuicontrol.cpp +++ b/src/ui/cuicontrol.cpp @@ -486,6 +486,10 @@ const Uint32& cUIControl::ControlFlags() const { return mControlFlags; } +void cUIControl::ControlFlags( const Uint32& Flags ) { + mControlFlags = Flags; +} + void cUIControl::CheckClose() { if ( mControlFlags & UI_CTRL_FLAG_DISABLE_CHECK_CLOSE_CHILDS ) return; diff --git a/src/ui/cuicontrol.hpp b/src/ui/cuicontrol.hpp index b2696f676..01e7a481b 100644 --- a/src/ui/cuicontrol.hpp +++ b/src/ui/cuicontrol.hpp @@ -168,6 +168,9 @@ class EE_API cUIControl { const Uint32& ControlFlags() const; + /** Use it at your own risk */ + void ControlFlags( const Uint32& Flags ); + Uint32 IsAnimated(); Uint32 IsClipped(); diff --git a/src/ui/cuievent.hpp b/src/ui/cuievent.hpp index c407282f7..74f073e6a 100644 --- a/src/ui/cuievent.hpp +++ b/src/ui/cuievent.hpp @@ -35,6 +35,7 @@ class EE_API cUIEvent { EventOnSelected, EventOnComplexControlFocusLoss, EventOnItemClicked, + EventOnHideByClick, EventUser, EventForceDWord = 0xFFFFFFFF }; diff --git a/src/ui/cuimenu.cpp b/src/ui/cuimenu.cpp index d33d75d28..e65c6904e 100644 --- a/src/ui/cuimenu.cpp +++ b/src/ui/cuimenu.cpp @@ -11,10 +11,13 @@ cUIMenu::cUIMenu( cUIMenu::CreateParams& Params ) : mFontShadowColor( Params.FontShadowColor ), mFontOverColor( Params.FontOverColor ), mMinWidth( Params.MinWidth ), + mMinSpaceForIcons( Params.MinSpaceForIcons ), mMaxWidth( 0 ), mRowHeight( Params.RowHeight ), mNextPosY( 0 ), - mBiggestIcon( 0 ) + mBiggestIcon( mMinSpaceForIcons ), + mItemSelected( NULL ), + mClickHide( false ) { mType |= UI_TYPE_GET( UI_TYPE_MENU ); @@ -86,6 +89,33 @@ Uint32 cUIMenu::AddCheckBox( const std::wstring& Text ) { return Add( CreateMenuCheckBox( Text ) ); } +cUIMenuSubMenu * cUIMenu::CreateSubMenu( const std::wstring& Text, cShape * Icon, cUIMenu * SubMenu ) { + cUIMenuSubMenu::CreateParams Params; + Params.Parent( this ); + Params.Font = mFont; + Params.FontColor = mFontColor; + Params.FontShadowColor = mFontShadowColor; + Params.FontOverColor = mFontOverColor; + Params.SubMenu = SubMenu; + Params.Flags = UI_CLIP_ENABLE | UI_VALIGN_CENTER | UI_HALIGN_LEFT; + + cUIMenuSubMenu * tCtrl = eeNew( cUIMenuSubMenu, ( Params ) ); + + tCtrl->Text( Text ); + + if ( NULL != Icon ) + tCtrl->Icon( Icon ); + + tCtrl->Visible( true ); + tCtrl->Enabled( true ); + + return tCtrl; +} + +Uint32 cUIMenu::AddSubMenu( const std::wstring& Text, cShape * Icon, cUIMenu * SubMenu ) { + return Add( CreateSubMenu( Text, Icon, SubMenu ) ); +} + bool cUIMenu::CheckControlSize( cUIControl * Control, const bool& Resize ) { if ( Control->IsType( UI_TYPE_MENUITEM ) ) { cUIMenuItem * tItem = reinterpret_cast ( Control ); @@ -95,13 +125,28 @@ bool cUIMenu::CheckControlSize( cUIControl * Control, const bool& Resize ) { } if ( mFlags & UI_AUTO_SIZE ) { - if ( tItem->TextBox()->GetTextWidth() + mBiggestIcon > (Int32)mMaxWidth - mPadding.Left - mPadding.Right ) { - mMaxWidth = tItem->TextBox()->GetTextWidth() + mBiggestIcon + mPadding.Left + mPadding.Right; + if ( Control->IsType( UI_TYPE_MENUSUBMENU ) ) { + cUIMenuSubMenu * tMenu = reinterpret_cast ( tItem ); - if ( Resize ) { - ResizeControls(); + if ( tMenu->TextBox()->GetTextWidth() + mBiggestIcon + tMenu->Arrow()->Size().Width() > (Int32)mMaxWidth - mPadding.Left - mPadding.Right ) { + mMaxWidth = tMenu->TextBox()->GetTextWidth() + mBiggestIcon + mPadding.Left + mPadding.Right + tMenu->Arrow()->Size().Width(); - return true; + if ( Resize ) { + ResizeControls(); + + return true; + } + } + } + else { + if ( tItem->TextBox()->GetTextWidth() + mBiggestIcon > (Int32)mMaxWidth - mPadding.Left - mPadding.Right ) { + mMaxWidth = tItem->TextBox()->GetTextWidth() + mBiggestIcon + mPadding.Left + mPadding.Right; + + if ( Resize ) { + ResizeControls(); + + return true; + } } } } @@ -232,6 +277,19 @@ void cUIMenu::Insert( cUIControl * Control, const Uint32& Index ) { ResizeControls(); } +bool cUIMenu::IsSubMenu( cUIControl * Ctrl ) { + for ( Uint32 i = 0; i < mItems.size(); i++ ) { + if ( mItems[i]->IsType( UI_TYPE_MENUSUBMENU ) ) { + cUIMenuSubMenu * tMenu = reinterpret_cast ( mItems[i] ); + + if ( tMenu->SubMenu() == Ctrl ) + return true; + } + } + + return false; +} + Uint32 cUIMenu::OnMessage( const cUIMessage * Msg ) { switch ( Msg->Msg() ) { case cUIMessage::MsgClick: @@ -245,7 +303,7 @@ Uint32 cUIMenu::OnMessage( const cUIMessage * Msg ) { { cUIControl * FocusCtrl = cUIManager::instance()->FocusControl(); - if ( this != FocusCtrl && !IsParentOf( FocusCtrl ) ) { + if ( this != FocusCtrl && !IsParentOf( FocusCtrl ) && !IsSubMenu( FocusCtrl ) ) { SendCommonEvent( cUIEvent::EventOnComplexControlFocusLoss ); OnComplexControlFocusLoss(); } @@ -274,17 +332,17 @@ void cUIMenu::AutoPadding() { } void cUIMenu::ResizeControls() { + ResizeMe(); + for ( Uint32 i = 0; i < mItems.size(); i++ ) { SetControlSize( mItems[i], i ); } - - ResizeMe(); } void cUIMenu::ReposControls() { Uint32 i; mNextPosY = 0; - mBiggestIcon = 0; + mBiggestIcon = mMinSpaceForIcons; if ( mFlags & UI_AUTO_SIZE ) { mMaxWidth = 0; @@ -311,4 +369,29 @@ void cUIMenu::ResizeMe() { } } +bool cUIMenu::Show() { + Enabled( true ); + Visible( true ); + return true; +} + +bool cUIMenu::Hide() { + Enabled( false ); + Visible( false ); + return true; +} + +void cUIMenu::SetItemSelected( cUIMenuItem * Item ) { + if ( NULL != mItemSelected ) { + if ( mItemSelected->IsType( UI_TYPE_MENUSUBMENU ) ) { + cUIMenuSubMenu * tMenu = reinterpret_cast ( mItemSelected ); + + if ( NULL != tMenu->SubMenu() ) + tMenu->SubMenu()->Hide(); + } + } + + mItemSelected = Item; +} + }} diff --git a/src/ui/cuimenu.hpp b/src/ui/cuimenu.hpp index a60339d19..30936c083 100644 --- a/src/ui/cuimenu.hpp +++ b/src/ui/cuimenu.hpp @@ -4,6 +4,7 @@ #include "cuicontrolanim.hpp" #include "cuimenuitem.hpp" #include "cuimenucheckbox.hpp" +#include "cuimenusubmenu.hpp" #include "cuiseparator.hpp" namespace EE { namespace UI { @@ -19,7 +20,8 @@ class EE_API cUIMenu : public cUIControlAnim { Font( NULL ), FontColor( 0, 0, 0, 255 ), FontOverColor( 0, 0, 0, 255 ), - MinWidth( 0 ) + MinWidth( 0 ), + MinSpaceForIcons( 0 ) { cUITheme * Theme = cUIThemeManager::instance()->DefaultTheme(); @@ -44,6 +46,7 @@ class EE_API cUIMenu : public cUIControlAnim { eeColorA FontShadowColor; eeColorA FontOverColor; Uint32 MinWidth; + Uint32 MinSpaceForIcons; }; @@ -59,6 +62,8 @@ class EE_API cUIMenu : public cUIControlAnim { Uint32 AddCheckBox( const std::wstring& Text ); + Uint32 AddSubMenu( const std::wstring& Text, cShape * Icon = NULL, cUIMenu * SubMenu = NULL ); + cUIControl * GetItem( const Uint32& Index ); cUIControl * GetItem( const std::wstring& Text ); @@ -76,8 +81,14 @@ class EE_API cUIMenu : public cUIControlAnim { void Insert( cUIControl * Control, const Uint32& Index ); virtual void SetTheme( cUITheme * Theme ); + + virtual bool Show(); + + virtual bool Hide(); protected: + friend class cUIMenuItem; friend class cUIMenuCheckBox; + friend class cUIMenuSubMenu; std::deque mItems; eeRecti mPadding; @@ -86,10 +97,13 @@ class EE_API cUIMenu : public cUIControlAnim { eeColorA mFontShadowColor; eeColorA mFontOverColor; Uint32 mMinWidth; + Uint32 mMinSpaceForIcons; Uint32 mMaxWidth; Uint32 mRowHeight; Uint32 mNextPosY; Uint32 mBiggestIcon; + cUIMenuItem * mItemSelected; + bool mClickHide; virtual void OnSizeChange(); @@ -108,10 +122,16 @@ class EE_API cUIMenu : public cUIControlAnim { cUIMenuItem * CreateMenuItem( const std::wstring& Text, cShape * Icon ); cUIMenuCheckBox * CreateMenuCheckBox( const std::wstring& Text ); + + cUIMenuSubMenu * CreateSubMenu( const std::wstring& Text, cShape * Icon, cUIMenu * SubMenu ); void DoAfterSetTheme(); bool CheckControlSize( cUIControl * Control, const bool& Resize = true ); + + bool IsSubMenu( cUIControl * Ctrl ); + + void SetItemSelected( cUIMenuItem * Item ); }; }} diff --git a/src/ui/cuimenucheckbox.cpp b/src/ui/cuimenucheckbox.cpp index cfc05b80d..d5e583786 100644 --- a/src/ui/cuimenucheckbox.cpp +++ b/src/ui/cuimenucheckbox.cpp @@ -76,7 +76,8 @@ void cUIMenuCheckBox::SwitchActive() { } Uint32 cUIMenuCheckBox::OnMouseClick( const eeVector2i &Pos, Uint32 Flags ) { - cUIPushButton::OnMouseClick( Pos, Flags ); + cUIMenuItem::OnMouseClick( Pos, Flags ); + SwitchActive(); return 1; diff --git a/src/ui/cuimenuitem.cpp b/src/ui/cuimenuitem.cpp index 2585a5b69..8179ab569 100644 --- a/src/ui/cuimenuitem.cpp +++ b/src/ui/cuimenuitem.cpp @@ -1,4 +1,5 @@ #include "cuimenuitem.hpp" +#include "cuimenu.hpp" namespace EE { namespace UI { @@ -18,4 +19,12 @@ void cUIMenuItem::SetTheme( cUITheme * Theme ) { DoAfterSetTheme(); } +Uint32 cUIMenuItem::OnMouseEnter( const eeVector2i &Pos, Uint32 Flags ) { + cUIPushButton::OnMouseEnter( Pos, Flags ); + + reinterpret_cast ( Parent() )->SetItemSelected( this ); + + return 1; +} + }} diff --git a/src/ui/cuimenuitem.hpp b/src/ui/cuimenuitem.hpp index 86bcd5323..e33aa92ae 100644 --- a/src/ui/cuimenuitem.hpp +++ b/src/ui/cuimenuitem.hpp @@ -12,6 +12,8 @@ class EE_API cUIMenuItem : public cUIPushButton { ~cUIMenuItem(); virtual void SetTheme( cUITheme * Theme ); + protected: + virtual Uint32 OnMouseEnter( const eeVector2i &Pos, Uint32 Flags ); }; }} diff --git a/src/ui/cuimenusubmenu.cpp b/src/ui/cuimenusubmenu.cpp new file mode 100644 index 000000000..9d3876659 --- /dev/null +++ b/src/ui/cuimenusubmenu.cpp @@ -0,0 +1,144 @@ +#include "cuimenusubmenu.hpp" +#include "cuimenu.hpp" +#include "cuimanager.hpp" + +namespace EE { namespace UI { + +cUIMenuSubMenu::cUIMenuSubMenu( cUIMenuSubMenu::CreateParams& Params ) : + cUIMenuItem( Params ), + mSubMenu( NULL ), + mSkinArrow( NULL ), + mArrow( NULL ), + mTimeOver( 0.f ), + mMaxTime( Params.MouseOverTimeShowMenu ), + mCbId( 0 ), + mCbId2( 0 ) +{ + mType |= UI_TYPE_GET( UI_TYPE_MENUSUBMENU ); + + cUIGfx::CreateParams GfxParams; + GfxParams.Parent( this ); + GfxParams.Shape = NULL; + GfxParams.Flags = UI_AUTO_SIZE; + mArrow = eeNew( cUIGfx, ( GfxParams ) ); + mArrow->Visible( true ); + mArrow->Enabled( false ); + + SubMenu( Params.SubMenu ); + + ApplyDefaultTheme(); +} + +cUIMenuSubMenu::~cUIMenuSubMenu() { +} + +void cUIMenuSubMenu::SetTheme( cUITheme * Theme ) { + cUIMenuItem::SetTheme( Theme ); + + mSkinArrow = Theme->GetByName( Theme->Abbr() + "_" + "menuarrow" ); + + OnStateChange(); +} + +void cUIMenuSubMenu::OnSizeChange() { + cUIMenuItem::OnSizeChange(); + + mArrow->Pos( Parent()->Size().Width() - mArrow->Size().Width() - 1, 0 ); + mArrow->CenterVertical(); +} + +void cUIMenuSubMenu::OnStateChange() { + cUIMenuItem::OnStateChange(); + + if ( NULL != mSkinArrow ) { + if ( mSkinState->GetState() == cUISkinState::StateMouseEnter ) + mArrow->Shape( mSkinArrow->GetShape( cUISkinState::StateMouseEnter ) ); + else + mArrow->Shape( mSkinArrow->GetShape( cUISkinState::StateNormal ) ); + + OnSizeChange(); + } +} + +void cUIMenuSubMenu::SubMenu( cUIMenu * SubMenu ) { + if ( NULL != mSubMenu && mSubMenu != SubMenu ) { + mSubMenu->RemoveEventListener( mCbId ); + mSubMenu->RemoveEventListener( mCbId2 ); + } + + mSubMenu = SubMenu; + + if ( NULL != mSubMenu ) { + mCbId = mSubMenu->AddEventListener( cUIEvent::EventOnEnabledChange, cb::Make1( this, &cUIMenuSubMenu::OnSubMenuFocusLoss ) ); + mCbId2 = mSubMenu->AddEventListener( cUIEvent::EventOnHideByClick, cb::Make1( this, &cUIMenuSubMenu::OnHideByClick ) ); + } +} + +cUIMenu * cUIMenuSubMenu::SubMenu() const { + return mSubMenu; +} + +Uint32 cUIMenuSubMenu::OnMouseMove( const eeVector2i &Pos, Uint32 Flags ) { + cUIMenuItem::OnMouseMove( Pos, Flags ); + + if ( NULL != mSubMenu && !mSubMenu->Visible() ) { + mTimeOver += cUIManager::instance()->Elapsed(); + + if ( mTimeOver >= mMaxTime ) { + ShowSubMenu(); + } + } + + return 1; +} + +void cUIMenuSubMenu::ShowSubMenu() { + mSubMenu->Parent( Parent()->Parent() ); + + eeVector2i Pos = this->Pos(); + + ControlToScreen( Pos ); + + Pos.x += mSize.Width(); + + mSubMenu->Pos( Pos ); + + if ( !mSubMenu->Visible() ) { + mSubMenu->Show(); + } +} + +Uint32 cUIMenuSubMenu::OnMouseExit( const eeVector2i &Pos, Uint32 Flags ) { + cUIMenuItem::OnMouseExit( Pos, Flags ); + + mTimeOver = 0; + + return 1; +} + +cUIGfx * cUIMenuSubMenu::Arrow() const { + return mArrow; +} + +void cUIMenuSubMenu::OnSubMenuFocusLoss( const cUIEvent * Event ) { + cUIControl * FocusCtrl = cUIManager::instance()->FocusControl(); + + if ( Parent() != FocusCtrl && !Parent()->IsParentOf( FocusCtrl ) ) { + cUIManager::instance()->FocusControl( Parent() ); + } + + if ( mSubMenu->mClickHide ) { + reinterpret_cast( Parent() )->Hide(); + + mSubMenu->mClickHide = false; + } +} + +void cUIMenuSubMenu::OnHideByClick( const cUIEvent * Event ) { + cUIMenu * tMenu = reinterpret_cast( Parent() ); + + tMenu->mClickHide = true; + tMenu->Hide(); +} + +}} diff --git a/src/ui/cuimenusubmenu.hpp b/src/ui/cuimenusubmenu.hpp new file mode 100644 index 000000000..8d28c6b3c --- /dev/null +++ b/src/ui/cuimenusubmenu.hpp @@ -0,0 +1,64 @@ +#ifndef EE_CUIMENUSUBMENU_HPP +#define EE_CUIMENUSUBMENU_HPP + +#include "cuimenuitem.hpp" + +namespace EE { namespace UI { + +class cUIMenu; + +class cUIMenuSubMenu : public cUIMenuItem { + public: + class CreateParams : public cUIMenuItem::CreateParams { + public: + inline CreateParams() : + cUIMenuItem::CreateParams(), + SubMenu( NULL ), + MouseOverTimeShowMenu( 200.f ) + { + } + + inline ~CreateParams() {} + + cUIMenu * SubMenu; + eeFloat MouseOverTimeShowMenu; + }; + + cUIMenuSubMenu( cUIMenuSubMenu::CreateParams& Params ); + + ~cUIMenuSubMenu(); + + virtual void SetTheme( cUITheme * Theme ); + + void SubMenu( cUIMenu * SubMenu ); + + cUIMenu * SubMenu() const; + + cUIGfx * Arrow() const; + protected: + cUIMenu * mSubMenu; + cUISkin * mSkinArrow; + cUIGfx * mArrow; + eeFloat mTimeOver; + eeFloat mMaxTime; + Uint32 mCbId; + Uint32 mCbId2; + + virtual Uint32 OnMouseExit( const eeVector2i &Pos, Uint32 Flags ); + + virtual Uint32 OnMouseMove( const eeVector2i &Pos, Uint32 Flags ); + + virtual void OnStateChange(); + + virtual void OnSizeChange(); + + void OnSubMenuFocusLoss( const cUIEvent * Event ); + + void OnHideByClick( const cUIEvent * Event ); + + void ShowSubMenu(); +}; + +}} + +#endif diff --git a/src/ui/cuipopupmenu.cpp b/src/ui/cuipopupmenu.cpp index f5497d5b8..c6546e2b0 100644 --- a/src/ui/cuipopupmenu.cpp +++ b/src/ui/cuipopupmenu.cpp @@ -58,7 +58,11 @@ Uint32 cUIPopUpMenu::OnMessage( const cUIMessage * Msg ) { switch ( Msg->Msg() ) { case cUIMessage::MsgClick: { - Hide(); + if ( !Msg->Sender()->IsType( UI_TYPE_MENUSUBMENU ) ) { + SendCommonEvent( cUIEvent::EventOnHideByClick ); + + Hide(); + } } } diff --git a/src/ui/cuipopupmenu.hpp b/src/ui/cuipopupmenu.hpp index 1fe5dd20e..932856e42 100644 --- a/src/ui/cuipopupmenu.hpp +++ b/src/ui/cuipopupmenu.hpp @@ -13,9 +13,9 @@ class cUIPopUpMenu : public cUIMenu { virtual void SetTheme( cUITheme * Theme ); - bool Show(); + virtual bool Show(); - bool Hide(); + virtual bool Hide(); protected: virtual void OnComplexControlFocusLoss(); diff --git a/src/ui/cuitheme.cpp b/src/ui/cuitheme.cpp index b3a536409..eac69a81d 100644 --- a/src/ui/cuitheme.cpp +++ b/src/ui/cuitheme.cpp @@ -49,7 +49,8 @@ static const char * UI_THEME_ELEMENTS[] = { "menuitem", "separator", "menucheckbox_active", - "menucheckbox_inactive" + "menucheckbox_inactive", + "menuarrow" }; cUITheme * cUITheme::LoadFromPath( const std::string& Path, const std::string& Name, const std::string& NameAbbr, const std::string ImgExt ) { diff --git a/src/ui/uihelper.hpp b/src/ui/uihelper.hpp index 3254253b3..86ffcfca3 100644 --- a/src/ui/uihelper.hpp +++ b/src/ui/uihelper.hpp @@ -78,6 +78,7 @@ Uint32 EE_API VAlignGet( Uint32 Flags ); #define UI_TYPE_MENU (17) #define UI_TYPE_MENUITEM (18) #define UI_TYPE_MENUCHECKBOX (19) +#define UI_TYPE_MENUSUBMENU (20) #define UI_TYPE_GET(X) ( 1 << (X) )