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) )