From cad28b6d6b9dc820fa358087bfbbf33ef956e845 Mon Sep 17 00:00:00 2001 From: spartanj Date: Fri, 24 Dec 2010 00:27:04 -0300 Subject: [PATCH] Added cUITextEdit ( not finished, but usable and working ). Fixed some minor bugs. --- src/audio/caudiodevice.cpp | 31 ++- src/audio/caudiodevice.hpp | 2 + src/ee.h | 1 + src/graphics/cfont.cpp | 6 + src/graphics/ctextcache.cpp | 4 - src/graphics/ctextcache.hpp | 2 - src/graphics/ctextureloader.cpp | 2 + src/test/ee.cpp | 28 ++- src/ui/cuicontrol.cpp | 6 +- src/ui/cuicontrol.hpp | 4 +- src/ui/cuidropdownlist.cpp | 2 +- src/ui/cuievent.hpp | 1 + src/ui/cuilistbox.cpp | 4 +- src/ui/cuilistbox.hpp | 7 +- src/ui/cuimenu.hpp | 9 +- src/ui/cuipushbutton.cpp | 2 +- src/ui/cuipushbutton.hpp | 7 +- src/ui/cuitextbox.cpp | 23 ++- src/ui/cuitextbox.hpp | 15 +- src/ui/cuitextedit.cpp | 340 ++++++++++++++++++++++++++++++++ src/ui/cuitextedit.hpp | 76 +++++++ src/ui/cuitextinput.cpp | 65 ++++-- src/ui/cuitextinput.hpp | 22 ++- src/ui/cuitheme.cpp | 2 + src/ui/uihelper.hpp | 9 +- src/window/cinputtextbuffer.cpp | 3 + 26 files changed, 598 insertions(+), 75 deletions(-) create mode 100644 src/ui/cuitextedit.cpp create mode 100644 src/ui/cuitextedit.hpp diff --git a/src/audio/caudiodevice.cpp b/src/audio/caudiodevice.cpp index 2fd81ec2b..241017958 100755 --- a/src/audio/caudiodevice.cpp +++ b/src/audio/caudiodevice.cpp @@ -10,6 +10,8 @@ cAudioDevice::cAudioDevice() : mContext(NULL), mRefCount(0) { + PrintInfo(); + // Create the device mDevice = alcOpenDevice( NULL ); @@ -23,10 +25,33 @@ cAudioDevice::cAudioDevice() : // Initialize the listener, located at the origin and looking along the Z axis cAudioListener::instance()->SetPosition(0.f, 0.f, 0.f); cAudioListener::instance()->SetTarget(0.f, 0.f, -1.f); - } else + + cLog::instance()->Write( "OpenAL current device: " ); + cLog::instance()->Write( "\t" + std::string( (const char *)alcGetString(mDevice, ALC_DEVICE_SPECIFIER) ) ); + } else { cLog::instance()->Write("Failed to create the audio context"); - } else + } + } else { cLog::instance()->Write("Failed to open the audio device"); + } +} + +void cAudioDevice::PrintInfo() { + cLog::instance()->Write( "OpenAL devices detected:" ); + + if ( alcIsExtensionPresent( NULL, (const ALCchar *) "ALC_ENUMERATION_EXT" ) == AL_TRUE ) { + const char *s = (const char *) alcGetString(NULL, ALC_DEVICE_SPECIFIER); + + while (*s != '\0') { + cLog::instance()->Write( "\t" + std::string( s ) ); + while (*s++ != '\0'); + } + } else { + cLog::instance()->Write( "OpenAL device enumeration isn't available." ); + } + + cLog::instance()->Write( "OpenAL default device: " ); + cLog::instance()->Write( "\t" + std::string( (const char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER) ) ); } cAudioDevice::~cAudioDevice() { @@ -76,7 +101,7 @@ ALCdevice * cAudioDevice::GetDevice() const { } bool cAudioDevice::IsExtensionSupported( const std::string& extension ) { - cAudioDevice::instance(); + cAudioDevice::instance(); if ( ( extension.length() > 2 ) && ( extension.substr(0, 3) == "ALC" ) ) return alcIsExtensionPresent( mDevice, extension.c_str() ) != AL_FALSE; diff --git a/src/audio/caudiodevice.hpp b/src/audio/caudiodevice.hpp index 8bf428daf..4f32a1781 100755 --- a/src/audio/caudiodevice.hpp +++ b/src/audio/caudiodevice.hpp @@ -30,6 +30,8 @@ class EE_API cAudioDevice { ALCdevice * mDevice; ALCcontext * mContext; unsigned int mRefCount; + + void PrintInfo(); }; }} diff --git a/src/ee.h b/src/ee.h index 510ce745e..6827f2e9a 100755 --- a/src/ee.h +++ b/src/ee.h @@ -168,5 +168,6 @@ #include "ui/cuiseparator.hpp" #include "ui/cuipopupmenu.hpp" #include "ui/cuisprite.hpp" + #include "ui/cuitextedit.hpp" using namespace EE::UI; #endif diff --git a/src/graphics/cfont.cpp b/src/graphics/cfont.cpp index a3ac122c0..f45488bac 100644 --- a/src/graphics/cfont.cpp +++ b/src/graphics/cfont.cpp @@ -562,6 +562,9 @@ void cFont::ShrinkText( std::string& Str, const Uint32& MaxWidth ) { *tStringLoop = '\n'; } + if ( L'\0' == *( tStringLoop + 1 ) ) + tStringLoop++; + tLastSpace = NULL; tCurWidth = 0.f; tPrev = -1; @@ -627,6 +630,9 @@ void cFont::ShrinkText( std::wstring& Str, const Uint32& MaxWidth ) { *tStringLoop = L'\n'; } + if ( L'\0' == *( tStringLoop + 1 ) ) + tStringLoop++; + // Set the last spaces as null, because is a new line tLastSpace = NULL; diff --git a/src/graphics/ctextcache.cpp b/src/graphics/ctextcache.cpp index dcd288d4a..ce1d5d7a9 100644 --- a/src/graphics/ctextcache.cpp +++ b/src/graphics/ctextcache.cpp @@ -159,10 +159,6 @@ void cTextCache::CachedCoords( const bool& cached ) { mCachedCoords = cached; } -cFont * cTextCache::GetFont() const { - return mFont; -} - const eeUint& cTextCache::CachedVerts() const { return mVertexNumCached; } diff --git a/src/graphics/ctextcache.hpp b/src/graphics/ctextcache.hpp index c3b801a30..732321f3d 100644 --- a/src/graphics/ctextcache.hpp +++ b/src/graphics/ctextcache.hpp @@ -56,8 +56,6 @@ class EE_API cTextCache { void ShadowColor(const eeColorA& Color); const eeInt& GetNumLines() const; - - cFont * GetFont() const; protected: friend class cFont; diff --git a/src/graphics/ctextureloader.cpp b/src/graphics/ctextureloader.cpp index f02f323ca..0a7d958bc 100644 --- a/src/graphics/ctextureloader.cpp +++ b/src/graphics/ctextureloader.cpp @@ -132,6 +132,8 @@ cTextureLoader::cTextureLoader( const unsigned char * Pixels, } cTextureLoader::~cTextureLoader() { + eeSAFE_DELETE( mColorKey ); + if ( TEX_LT_PIXELS != mLoadType ) eeSAFE_FREE( mPixels ); } diff --git a/src/test/ee.cpp b/src/test/ee.cpp index 373cc5439..ecc1344a3 100644 --- a/src/test/ee.cpp +++ b/src/test/ee.cpp @@ -289,6 +289,7 @@ void cEETest::Init() { Scenes[2] = cb::Make0( this, &cEETest::Screen3 ); InBuf.Start(); + InBuf.SupportNewLine( true ); SetRandomSeed(); @@ -389,15 +390,15 @@ void cEETest::CreateShaders() { void cEETest::CreateUI() { cUIManager::instance()->Init(); - cUIControl::CreateParams Params( cUIManager::instance()->MainControl(), eeVector2i(0,0), eeSize( 530, 240 ), UI_FILL_BACKGROUND | UI_CLIP_ENABLE | UI_BORDER ); + cUIControl::CreateParams Params( cUIManager::instance()->MainControl(), eeVector2i(0,0), eeSize( 530, 380 ), UI_FILL_BACKGROUND | UI_CLIP_ENABLE | UI_BORDER ); - //cUIThemeManager::instance()->Add( cUITheme::LoadFromPath( MyPath + "data/aqua/", "aqua", "aqua" ) ); + cUIThemeManager::instance()->Add( cUITheme::LoadFromPath( MyPath + "data/aqua/", "aqua", "aqua" ) ); CreateAquaTextureAtlas(); - +/* cTextureGroupLoader tgl( MyPath + "data/aquatg/aqua.etg" ); TF->GetByName( "data/aquatg/aqua.png" )->TextureFilter( TEX_FILTER_NEAREST ); cUIThemeManager::instance()->Add( cUITheme::LoadFromShapeGroup( cShapeGroupManager::instance()->GetByName( "aqua" ), "aqua", "aqua" ) ); - +*/ cUIThemeManager::instance()->DefaultEffectsEnabled( true ); cUIThemeManager::instance()->DefaultFont( TTF ); cUIThemeManager::instance()->DefaultTheme( "aqua" ); @@ -457,8 +458,6 @@ void cEETest::CreateUI() { cUITextInput::CreateParams InputParams; InputParams.Parent( C ); - InputParams.Border.Color(0xFF979797); - InputParams.Background.Colors( eeColorA(0x99AAAAAA), eeColorA(0x99CCCCCC), eeColorA(0x99CCCCCC), eeColorA(0x99AAAAAA) ); InputParams.PosSet( 20, 216 ); InputParams.Size = eeSize( 200, 22 ); InputParams.Flags = UI_VALIGN_CENTER | UI_HALIGN_LEFT | UI_CLIP_ENABLE | UI_AUTO_PADDING; @@ -596,7 +595,7 @@ void cEETest::CreateUI() { ComboParams.Parent( C ); ComboParams.PosSet( 20, 80 ); ComboParams.Size = eeSize( 100, 19 ); - DDLParams.Flags = UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_VALIGN_CENTER | UI_HALIGN_LEFT; + ComboParams.Flags = UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_VALIGN_CENTER | UI_HALIGN_LEFT; cUIComboBox * mComboBox = eeNew( cUIComboBox, ( ComboParams ) ); mComboBox->Visible( true ); mComboBox->Enabled( true ); @@ -652,7 +651,20 @@ void cEETest::CreateUI() { C->StartAlphaAnim( 0.f, 255.f, 500.f ); C->StartRotation( 0, 360, 500.f, SINEOUT ); + cUITextEdit::CreateParams TEParams; + TEParams.Parent( C ); + TEParams.PosSet( 5, 245 ); + TEParams.Size = eeSize( 315, 130 ); + TEParams.Flags = UI_AUTO_PADDING | UI_CLIP_ENABLE; + TEParams.WordWrap = false; + cUITextEdit * TextEdit = eeNew( cUITextEdit, ( TEParams ) ); + TextEdit->Visible( true ); + TextEdit->Enabled( true ); + mBuda = L"El mono ve el pez en el agua y sufre. Piensa que su mundo es el único que existe, el mejor, el real. Sufre porque es bueno y tiene compasión, lo ve y piensa: \"Pobre se está ahogando no puede respirar\". Y lo saca, lo saca y se queda tranquilo, por fin lo salvé. Pero el pez se retuerce de dolor y muere. Por eso te mostré el sueño, es imposible meter el mar en tu cabeza, que es un balde."; + + //TextEdit->Text( mBuda ); + TTFB->ShrinkText( mBuda, 400 ); mBudaTC.Create( TTFB, mBuda, eeColorA(255,255,255,255) ); @@ -1165,7 +1177,7 @@ void cEETest::Render() { PR.DrawRectangle( 0.f, - (eeFloat)EE->GetHeight() - (eeFloat)mEEText.GetNumLines() * (eeFloat)mEEText.GetFont()->GetFontSize(), + (eeFloat)EE->GetHeight() - (eeFloat)mEEText.GetNumLines() * (eeFloat)mEEText.Font()->GetFontSize(), mEEText.GetTextWidth(), mEEText.GetTextHeight(), ColRR1, ColRR2, ColRR3, ColRR4 diff --git a/src/ui/cuicontrol.cpp b/src/ui/cuicontrol.cpp index f2c449483..3da381841 100644 --- a/src/ui/cuicontrol.cpp +++ b/src/ui/cuicontrol.cpp @@ -131,8 +131,10 @@ const eeVector2i& cUIControl::Pos() const { } void cUIControl::Size( const eeSize& Size ) { - mSize = Size; - OnSizeChange(); + if ( Size != mSize ) { + mSize = Size; + OnSizeChange(); + } } void cUIControl::Size( const Int32& Width, const Int32& Height ) { diff --git a/src/ui/cuicontrol.hpp b/src/ui/cuicontrol.hpp index d4c9bc239..6a8995199 100644 --- a/src/ui/cuicontrol.hpp +++ b/src/ui/cuicontrol.hpp @@ -307,6 +307,8 @@ class EE_API cUIControl { virtual cUIControl * OverFind( const eeVector2f& Point ); + void ClipMe(); + void CheckClose(); void InternalDraw(); @@ -329,8 +331,6 @@ class EE_API cUIControl { cUIControl * ChildNext( cUIControl * Ctrl, bool Loop = false ) const; - void ClipMe(); - void ClipDisable(); void ClipTo(); diff --git a/src/ui/cuidropdownlist.cpp b/src/ui/cuidropdownlist.cpp index 8b1fb3863..bde57e88e 100644 --- a/src/ui/cuidropdownlist.cpp +++ b/src/ui/cuidropdownlist.cpp @@ -104,7 +104,7 @@ void cUIDropDownList::OnItemClicked( const cUIEvent * Event ) { } void cUIDropDownList::OnItemSelected( const cUIEvent * Event ) { - Text( mListBox->GetItemSelectedText() ); + mTextBuffer.Buffer( mListBox->GetItemSelectedText() ); } void cUIDropDownList::Show() { diff --git a/src/ui/cuievent.hpp b/src/ui/cuievent.hpp index 0f0dd2c14..bf124632c 100644 --- a/src/ui/cuievent.hpp +++ b/src/ui/cuievent.hpp @@ -38,6 +38,7 @@ class EE_API cUIEvent { EventOnHideByClick, EventOnItemKeyDown, EventOnItemKeyUp, + EventOnCursorPosChange, EventUser, EventForceDWord = 0xFFFFFFFF }; diff --git a/src/ui/cuilistbox.cpp b/src/ui/cuilistbox.cpp index 10aa0bf6e..6bab8b61b 100644 --- a/src/ui/cuilistbox.cpp +++ b/src/ui/cuilistbox.cpp @@ -342,9 +342,9 @@ void cUIListBox::ContainerResize() { mContainer->Pos( mPaddingContainer.Left, mPaddingContainer.Top ); if( mHScrollBar->Visible() ) - mContainer->Size( mSize.Width() - mPaddingContainer.Right - mPaddingContainer.Left, mSize.Height() - mPaddingContainer.Top - mPaddingContainer.Bottom - mHScrollBar->Size().Height() ); + mContainer->Size( mSize.Width() - mPaddingContainer.Right - mPaddingContainer.Left, mSize.Height() - mPaddingContainer.Top - mHScrollBar->Size().Height() ); else - mContainer->Size( mSize.Width() - mPaddingContainer.Right - mPaddingContainer.Left, mSize.Height() - mPaddingContainer.Top - mPaddingContainer.Bottom ); + mContainer->Size( mSize.Width() - mPaddingContainer.Right - mPaddingContainer.Left, mSize.Height() - mPaddingContainer.Bottom - mPaddingContainer.Top ); } void cUIListBox::CreateItemIndex( const Uint32& i ) { diff --git a/src/ui/cuilistbox.hpp b/src/ui/cuilistbox.hpp index b41875afa..9571f0632 100644 --- a/src/ui/cuilistbox.hpp +++ b/src/ui/cuilistbox.hpp @@ -28,14 +28,13 @@ class EE_API cUIListBox : public cUIControlAnim { if ( NULL != Theme ) { Font = Theme->Font(); - - if ( NULL == Font ) - Font = cUIThemeManager::instance()->DefaultFont(); - FontColor = Theme->FontColor(); FontOverColor = Theme->FontOverColor(); FontSelectedColor = Theme->FontSelectedColor(); } + + if ( NULL == Font ) + Font = cUIThemeManager::instance()->DefaultFont(); } inline ~CreateParams() {} diff --git a/src/ui/cuimenu.hpp b/src/ui/cuimenu.hpp index fb28ff01b..927deb12a 100644 --- a/src/ui/cuimenu.hpp +++ b/src/ui/cuimenu.hpp @@ -28,16 +28,15 @@ class EE_API cUIMenu : public cUIControlAnim { cUITheme * Theme = cUIThemeManager::instance()->DefaultTheme(); if ( NULL != Theme ) { - Font = Theme->Font(); - - if ( NULL == Font ) - Font = cUIThemeManager::instance()->DefaultFont(); - + Font = Theme->Font(); FontColor = Theme->FontColor(); FontShadowColor = Theme->FontShadowColor(); FontOverColor = Theme->FontOverColor(); FontSelectedColor = Theme->FontSelectedColor(); } + + if ( NULL == Font ) + Font = cUIThemeManager::instance()->DefaultFont(); } inline ~CreateParams() {} diff --git a/src/ui/cuipushbutton.cpp b/src/ui/cuipushbutton.cpp index fd208ead7..0e738bca0 100644 --- a/src/ui/cuipushbutton.cpp +++ b/src/ui/cuipushbutton.cpp @@ -72,7 +72,7 @@ void cUIPushButton::OnSizeChange() { if ( mFlags & UI_AUTO_SIZE ) { if ( NULL != mTextBox ) { - eeRecti P = MakePadding( true, true, true, true, true ); + eeRecti P = MakePadding(); mSize.Height( mIcon->Size().Height() + P.Top + P.Bottom ); diff --git a/src/ui/cuipushbutton.hpp b/src/ui/cuipushbutton.hpp index bffb887c5..995223c46 100644 --- a/src/ui/cuipushbutton.hpp +++ b/src/ui/cuipushbutton.hpp @@ -24,14 +24,13 @@ class EE_API cUIPushButton : public cUIControlAnim { if ( NULL != Theme ) { Font = Theme->Font(); - - if ( NULL == Font ) - Font = cUIThemeManager::instance()->DefaultFont(); - FontColor = Theme->FontColor(); FontShadowColor = Theme->FontShadowColor(); FontOverColor = Theme->FontOverColor(); } + + if ( NULL == Font ) + Font = cUIThemeManager::instance()->DefaultFont(); } inline ~CreateParams() {} diff --git a/src/ui/cuitextbox.cpp b/src/ui/cuitextbox.cpp index 099a45df6..915e4fe44 100644 --- a/src/ui/cuitextbox.cpp +++ b/src/ui/cuitextbox.cpp @@ -36,13 +36,20 @@ void cUITextBox::Draw() { cUIControlAnim::Draw(); if ( mTextCache->GetTextWidth() ) { - if ( mFlags & UI_CLIP_ENABLE ) - cEngine::instance()->ClipPlaneEnable( mScreenPos.x + mPadding.Left, mScreenPos.y + mPadding.Top, mSize.Width() - mPadding.Left - mPadding.Right, mSize.Height() - mPadding.Bottom ); + if ( mFlags & UI_CLIP_ENABLE ) { + cEngine::instance()->ClipPlaneEnable( + mScreenPos.x + mPadding.Left, + mScreenPos.y + mPadding.Top, + mSize.Width() - mPadding.Left - mPadding.Right, + mSize.Height() - mPadding.Top - mPadding.Bottom + ); + } mTextCache->Draw( (eeFloat)mScreenPos.x + mAlignOffset.x + (eeFloat)mPadding.Left + 1.f, (eeFloat)mScreenPos.y + mAlignOffset.y + (eeFloat)mPadding.Top, Flags(), 1.f, 0.f, mBlend ); - if ( mFlags & UI_CLIP_ENABLE ) + if ( mFlags & UI_CLIP_ENABLE ) { cEngine::instance()->ClipPlaneDisable(); + } } } } @@ -105,13 +112,17 @@ void cUITextBox::Alpha( const eeFloat& alpha ) { } void cUITextBox::AutoShrink() { - if ( Flags() & UI_AUTO_SHRINK_TEXT ) { - mTextCache->Font()->ShrinkText( mTextCache->Text(), mSize.Width() ); + if ( mFlags & UI_AUTO_SHRINK_TEXT ) { + ShrinkText( mSize.Width() ); } } +void cUITextBox::ShrinkText( const Uint32& MaxWidth ) { + mTextCache->Font()->ShrinkText( mTextCache->Text(), MaxWidth ); +} + void cUITextBox::AutoSize() { - if ( Flags() & UI_AUTO_SIZE ) { + if ( mFlags & UI_AUTO_SIZE ) { mSize.Width( (eeInt)mTextCache->GetTextWidth() ); mSize.Height( (eeInt)mTextCache->GetTextHeight() ); } diff --git a/src/ui/cuitextbox.hpp b/src/ui/cuitextbox.hpp index 710660c00..3dba3907e 100644 --- a/src/ui/cuitextbox.hpp +++ b/src/ui/cuitextbox.hpp @@ -19,13 +19,12 @@ class EE_API cUITextBox : public cUIControlAnim { if ( NULL != Theme ) { Font = Theme->Font(); - - if ( NULL == Font ) - Font = cUIThemeManager::instance()->DefaultFont(); - FontColor = Theme->FontColor(); FontShadowColor = Theme->FontShadowColor(); } + + if ( NULL == Font ) + Font = cUIThemeManager::instance()->DefaultFont(); } inline ~CreateParams() {} @@ -80,6 +79,8 @@ class EE_API cUITextBox : public cUIControlAnim { const eeInt& GetNumLines() const; const eeVector2f& AlignOffset() const; + + virtual void ShrinkText( const Uint32& MaxWidth ); protected: cTextCache * mTextCache; eeColorA mFontColor; @@ -89,11 +90,11 @@ class EE_API cUITextBox : public cUIControlAnim { virtual void OnSizeChange(); - void AutoShrink(); + virtual void AutoShrink(); - void AutoSize(); + virtual void AutoSize(); - void AutoAlign(); + virtual void AutoAlign(); }; }} diff --git a/src/ui/cuitextedit.cpp b/src/ui/cuitextedit.cpp new file mode 100644 index 000000000..b79624697 --- /dev/null +++ b/src/ui/cuitextedit.cpp @@ -0,0 +1,340 @@ +#include "cuitextedit.hpp" + +namespace EE { namespace UI { + +cUITextEdit::cUITextEdit( cUITextEdit::CreateParams& Params ) : + + cUIControlAnim( Params ), + mTextInput( NULL ), + mHScrollBar( NULL ), + mVScrollBar( NULL ), + mHScrollBarMode( Params.HScrollBar ), + mVScrollBarMode( Params.VScrollBar ), + mSkipValueChange( false ) +{ + mType |= UI_TYPE_GET( UI_TYPE_TEXTEDIT ); + + cUITextInput::CreateParams TIParams; + TIParams.Parent( this ); + TIParams.Size = mSize; + TIParams.Flags = UI_VALIGN_TOP | UI_HALIGN_LEFT; + TIParams.MaxLenght = 1024 * 1024 * 10; + TIParams.Font = Params.Font; + TIParams.FontColor = Params.FontColor; + TIParams.FontShadowColor = Params.FontShadowColor; + + if ( Params.WordWrap && !( mFlags & UI_AUTO_SHRINK_TEXT ) ) + mFlags |= UI_AUTO_SHRINK_TEXT; + + mTextInput = eeNew( cUITextInput, ( TIParams ) ); + mTextInput->GetInputTextBuffer()->SupportNewLine( true ); + mTextInput->Visible( true ); + mTextInput->Enabled( true ); + mTextInput->AddEventListener( cUIEvent::EventOnSizeChange , cb::Make1( this, &cUITextEdit::OnInputSizeChange ) ); + mTextInput->AddEventListener( cUIEvent::EventOnTextChanged , cb::Make1( this, &cUITextEdit::OnInputSizeChange ) ); + mTextInput->AddEventListener( cUIEvent::EventOnPressEnter , cb::Make1( this, &cUITextEdit::OnInputSizeChange ) ); + mTextInput->AddEventListener( cUIEvent::EventOnCursorPosChange , cb::Make1( this, &cUITextEdit::OnCursorPosChange ) ); + + cUIScrollBar::CreateParams ScrollBarP; + ScrollBarP.Parent( this ); + ScrollBarP.PosSet( mSize.Width() - 15, 0 ); + ScrollBarP.Size = eeSize( 15, mSize.Height() ); + ScrollBarP.Flags = UI_AUTO_SIZE; + ScrollBarP.VerticalScrollBar = true; + mVScrollBar = eeNew( cUIScrollBar, ( ScrollBarP ) ); + mVScrollBar->Value( 1 ); + + ScrollBarP.PosSet( 0, mSize.Height() - 15 ); + ScrollBarP.Size = eeSize( mSize.Width() - mVScrollBar->Size().Width(), 15 ); + ScrollBarP.VerticalScrollBar = false; + mHScrollBar = eeNew( cUIScrollBar, ( ScrollBarP ) ); + + mVScrollBar->AddEventListener( cUIEvent::EventOnValueChange, cb::Make1( this, &cUITextEdit::OnVScrollValueChange ) ); + mHScrollBar->AddEventListener( cUIEvent::EventOnValueChange, cb::Make1( this, &cUITextEdit::OnHScrollValueChange ) ); + + AutoPadding(); + + OnSizeChange(); + + ApplyDefaultTheme(); + + mTextInput->Size( mSize - eeSize( mPadding.Left + mPadding.Right, mPadding.Top + mPadding.Bottom ) ); +} + +cUITextEdit::~cUITextEdit() { +} + +void cUITextEdit::SetTheme( cUITheme * Theme ) { + cUIControl::SetTheme( Theme, "textedit" ); + + mTextInput->ForceThemeSkin( Theme, "textedit_box" ); + + mHScrollBar->Pos( 0, mSize.Height() - mHScrollBar->Size().Height() ); + mVScrollBar->Pos( mSize.Width() - mVScrollBar->Size().Width(), 0 ); + + mHScrollBar->Size( mSize.Width(), mHScrollBar->Size().Height() ); + mVScrollBar->Size( mVScrollBar->Size().Width(), mSize.Height() ); + + AutoPadding(); + + OnSizeChange(); +} + +void cUITextEdit::OnSizeChange() { + mTextInput->Pos( mPadding.Left, mPadding.Top ); + + ScrollbarsSet(); + + FixScroll(); +} + +void cUITextEdit::FixScroll() { + eeInt Width = mSize.Width() - mPadding.Left - mPadding.Right; + eeInt Height = mSize.Height() - mPadding.Top - mPadding.Bottom; + + if ( mHScrollBar->Visible() ) + Height -= mHScrollBar->Size().Height(); + + eeInt diff; + eeFloat pos; + + if ( mTextInput->Size().Height() - Height >= 0 ) { + diff = mTextInput->Size().Height() - Height; + + pos = diff * mVScrollBar->Value(); + + mTextInput->Pos( mTextInput->Pos().x, mPadding.Top - pos ); + } + + if ( mTextInput->Size().Width() - Width >= 0 ) { + diff = mTextInput->Size().Width() - Width; + + pos = diff * mHScrollBar->Value(); + + mTextInput->Pos( mPadding.Left - pos, mTextInput->Pos().y ); + } +} + +void cUITextEdit::ScrollbarsSet() { + switch ( mHScrollBarMode ) { + case UI_SCROLLBAR_ALWAYS_OFF: + { + mHScrollBar->Visible( false ); + mHScrollBar->Enabled( false ); + break; + } + case UI_SCROLLBAR_ALWAYS_ON: + { + mHScrollBar->Visible( true ); + mHScrollBar->Enabled( true ); + break; + } + case UI_SCROLLBAR_AUTO: + { + if ( mTextInput->GetTextWidth() > mSize.Width() - mPadding.Left - mPadding.Right ) { + mHScrollBar->Visible( true ); + mHScrollBar->Enabled( true ); + } else { + mHScrollBar->Visible( false ); + mHScrollBar->Enabled( false ); + } + break; + } + } + + switch ( mVScrollBarMode ) { + case UI_SCROLLBAR_ALWAYS_OFF: + { + mVScrollBar->Visible( false ); + mVScrollBar->Enabled( false ); + break; + } + case UI_SCROLLBAR_ALWAYS_ON: + { + mVScrollBar->Visible( true ); + mVScrollBar->Enabled( true ); + break; + } + case UI_SCROLLBAR_AUTO: + { + eeInt extraH = 0; + + if ( mHScrollBar->Visible() ) + extraH = mHScrollBar->Size().Height(); + + if ( mTextInput->GetTextHeight() > mSize.Height() - mPadding.Top - mPadding.Bottom - extraH ) { + mVScrollBar->Visible( true ); + mVScrollBar->Enabled( true ); + } else { + mVScrollBar->Visible( false ); + mVScrollBar->Enabled( false ); + } + break; + } + } + + if ( !mVScrollBar->Visible() && mHScrollBar->Visible() ) { + mHScrollBar->Size( mSize.Width(), mHScrollBar->Size().Height() ); + } else { + mHScrollBar->Size( mSize.Width() - mVScrollBar->Size().Width(), mHScrollBar->Size().Height() ); + } + + if ( UI_SCROLLBAR_AUTO == mHScrollBarMode && mVScrollBar->Visible() && !mHScrollBar->Visible() ) { + if ( mTextInput->GetTextWidth() > mSize.Width() - mPadding.Left - mPadding.Right - mVScrollBar->Size().Width() ) { + mHScrollBar->Visible( true ); + mHScrollBar->Enabled( true ); + } + } + + if ( ( mFlags & UI_AUTO_SHRINK_TEXT ) ) { + mVScrollBar->Visible( true ); + mVScrollBar->Enabled( true ); + } +} + +void cUITextEdit::AutoPadding() { + if ( mFlags & UI_AUTO_PADDING ) { + mPadding = MakePadding(); + } +} + +void cUITextEdit::OnVScrollValueChange( const cUIEvent * Event ) { + if ( !mSkipValueChange ) + FixScroll(); +} + +void cUITextEdit::OnHScrollValueChange( const cUIEvent * Event ) { + if ( !mSkipValueChange ) + FixScroll(); +} + +cUITextInput * cUITextEdit::TextInput() const { + return mTextInput; +} + +cUIScrollBar * cUITextEdit::HScrollBar() const { + return mHScrollBar; +} + +cUIScrollBar * cUITextEdit::VScrollBar() const { + return mVScrollBar; +} + +const std::wstring& cUITextEdit::Text() const { + return mTextInput->Text(); +} + +void cUITextEdit::Text( const std::wstring& Txt ) { + mTextInput->Text( Txt ); + + OnInputSizeChange(); + + OnSizeChange(); +} + +void cUITextEdit::Text( const std::string& Txt ) { + Text( stringTowstring( Txt ) ); +} + +void cUITextEdit::OnInputSizeChange( const cUIEvent * Event ) { + eeInt Width = mSize.Width() - mPadding.Left - mPadding.Right; + eeInt Height = mSize.Height() - mPadding.Top - mPadding.Bottom; + + if ( NULL != Event ) { + if ( Event->EventType() == cUIEvent::EventOnPressEnter ) { + mHScrollBar->Value( 0 ); + } + } + + ScrollbarsSet(); + + if ( mHScrollBar->Visible() ) + Height -= mHScrollBar->Size().Height(); + + if ( mVScrollBar->Visible() ) + Width -= mVScrollBar->Size().Width(); + + + if ( Flags() & UI_AUTO_SHRINK_TEXT ) { + mTextInput->ShrinkText( Width ); + } + + if ( mTextInput->Size().Width() < Width || mTextInput->Size().Height() < Height ) { + if ( mTextInput->Size().Width() < Width && mTextInput->Size().Height() < Height ) { + mTextInput->Size( Width, Height ); + } else { + if ( mTextInput->Size().Width() < Width ) { + mTextInput->Size( Width, mTextInput->Size().Height() ); + } else { + mTextInput->Size( mTextInput->Size().Width(), Height ); + } + } + } + + if ( mTextInput->GetTextWidth() > Width || mTextInput->GetTextHeight() > Height ) { + if ( mTextInput->GetTextWidth() > Width && mTextInput->GetTextHeight() > Height ) { + mTextInput->Size( mTextInput->GetTextWidth(), mTextInput->GetTextHeight() ); + } else { + if ( mTextInput->GetTextWidth() > Width ) { + mTextInput->Size( mTextInput->GetTextWidth(), Height ); + } else { + mTextInput->Size( Width, mTextInput->GetTextHeight() ); + } + } + } else { + mTextInput->Size( Width, Height ); + } + + FixScroll(); + FixScrollToCursor(); +} + +void cUITextEdit::OnCursorPosChange( const cUIEvent * Event ) { + FixScrollToCursor(); +} + +void cUITextEdit::FixScrollToCursor() { + eeInt Width = mSize.Width() - mPadding.Left - mPadding.Right; + eeInt Height = mSize.Height() - mPadding.Top - mPadding.Bottom; + + if ( mVScrollBar->Visible() ) + Width -= mVScrollBar->Size().Width(); + + if ( mHScrollBar->Visible() ) + Height -= mHScrollBar->Size().Height(); + + if ( FontHAlignGet( mTextInput->Flags() ) == UI_HALIGN_LEFT ) { + Uint32 NLPos = 0; + Uint32 LineNum = mTextInput->GetInputTextBuffer()->GetCurPosLinePos( NLPos ); + + mTextInput->GetTextCache()->Font()->SetText( + mTextInput->GetInputTextBuffer()->Buffer().substr( + NLPos, mTextInput->GetInputTextBuffer()->CurPos() - NLPos + ) + ); + + mSkipValueChange = true; + + eeFloat tW = mTextInput->GetTextCache()->Font()->GetTextWidth(); + eeFloat tH = (eeFloat)(LineNum + 1) * (eeFloat)mTextInput->GetTextCache()->Font()->GetFontSize(); + + if ( tW > Width ) { + mTextInput->Pos( mPadding.Left + Width - tW, mTextInput->Pos().y ); + } else { + mTextInput->Pos( mPadding.Left, mTextInput->Pos().y ); + } + + if ( tH > Height ) { + mTextInput->Pos( mTextInput->Pos().x, mPadding.Top + Height - tH ); + } else { + mTextInput->Pos( mTextInput->Pos().x, mPadding.Top ); + } + + mHScrollBar->Value( tW / mTextInput->Size().Width() ); + mVScrollBar->Value( tH / mTextInput->Size().Height() ); + + mSkipValueChange = false; + } +} + +}} diff --git a/src/ui/cuitextedit.hpp b/src/ui/cuitextedit.hpp new file mode 100644 index 000000000..c5c7ce114 --- /dev/null +++ b/src/ui/cuitextedit.hpp @@ -0,0 +1,76 @@ +#ifndef EE_UICUITEXTEDIT_HPP +#define EE_UICUITEXTEDIT_HPP + +#include "cuicontrolanim.hpp" +#include "cuitextinput.hpp" +#include "cuiscrollbar.hpp" + +namespace EE { namespace UI { + +class EE_API cUITextEdit : public cUIControlAnim { + public: + class CreateParams : public cUITextBox::CreateParams { + public: + inline CreateParams() : cUITextBox::CreateParams(), + HScrollBar( UI_SCROLLBAR_AUTO ), + VScrollBar( UI_SCROLLBAR_AUTO ), + WordWrap( true ) + { + } + + inline ~CreateParams() {} + + UI_SCROLLBAR_MODE HScrollBar; + UI_SCROLLBAR_MODE VScrollBar; + bool WordWrap; + }; + + cUITextEdit( cUITextEdit::CreateParams& Params ); + + ~cUITextEdit(); + + virtual void SetTheme( cUITheme * Theme ); + + const std::wstring& Text() const; + + void Text( const std::wstring& Txt ); + + void Text( const std::string& Txt ); + + cUITextInput * TextInput() const; + + cUIScrollBar * HScrollBar() const; + + cUIScrollBar * VScrollBar() const; + protected: + cUITextInput * mTextInput; + cUIScrollBar * mHScrollBar; + cUIScrollBar * mVScrollBar; + UI_SCROLLBAR_MODE mHScrollBarMode; + UI_SCROLLBAR_MODE mVScrollBarMode; + eeRecti mPadding; + std::wstring mText; + bool mSkipValueChange; + + virtual void OnSizeChange(); + + void OnVScrollValueChange( const cUIEvent * Event ); + + void OnHScrollValueChange( const cUIEvent * Event ); + + void OnInputSizeChange( const cUIEvent * Event = NULL ); + + void OnCursorPosChange( const cUIEvent * Event ); + + void AutoPadding(); + + void ScrollbarsSet(); + + void FixScroll(); + + void FixScrollToCursor(); +}; + +}} + +#endif diff --git a/src/ui/cuitextinput.cpp b/src/ui/cuitextinput.cpp index e8b5eb0a5..6fa34ed29 100644 --- a/src/ui/cuitextinput.cpp +++ b/src/ui/cuitextinput.cpp @@ -28,7 +28,7 @@ void cUITextInput::Update() { if ( mTextBuffer.ChangedSinceLastUpdate() ) { eeVector2f offSet = mAlignOffset; - Text( mTextBuffer.Buffer() ); + cUITextBox::Text( mTextBuffer.Buffer() ); mAlignOffset = offSet; @@ -38,15 +38,22 @@ void cUITextInput::Update() { mCursorPos = mTextBuffer.CurPos(); + mTextBuffer.ChangedSinceLastUpdate( false ); + return; } if ( mCursorPos != mTextBuffer.CurPos() ) { AlignFix(); mCursorPos = mTextBuffer.CurPos(); + OnCursorPosChange(); } } +void cUITextInput::OnCursorPosChange() { + SendCommonEvent( cUIEvent::EventOnCursorPosChange ); +} + void cUITextInput::Draw() { cUITextBox::Draw(); @@ -63,7 +70,7 @@ void cUITextInput::Draw() { P.SetColor( mFontColor ); eeFloat CurPosX = mScreenPos.x + mAlignOffset.x + mCurPos.x + 1 + mPadding.Left; - eeFloat CurPosY = mScreenPos.y + mAlignOffset.y + mCurPos.y + mPadding.Top; + eeFloat CurPosY = mScreenPos.y + mAlignOffset.y + mCurPos.y + mPadding.Top; if ( CurPosX > (eeFloat)mScreenPos.x + (eeFloat)mSize.x ) CurPosX = (eeFloat)mScreenPos.x + (eeFloat)mSize.x; @@ -120,25 +127,25 @@ void cUITextInput::ResetWaitCursor() { } void cUITextInput::AlignFix() { - if ( !( FontHAlignGet( Flags() ) == UI_HALIGN_LEFT && !mTextBuffer.SupportNewLine() ) ) - return; + if ( FontHAlignGet( Flags() ) == UI_HALIGN_LEFT ) { + Uint32 NLPos = 0; + Uint32 LineNum = mTextBuffer.GetCurPosLinePos( NLPos ); - Uint32 NLPos = 0; - Uint32 LineNum = mTextBuffer.GetCurPosLinePos( NLPos ); + mTextCache->Font()->SetText( mTextBuffer.Buffer().substr( NLPos, mTextBuffer.CurPos() - NLPos ) ); - mTextCache->Font()->SetText( mTextBuffer.Buffer().substr( NLPos, mTextBuffer.CurPos() - NLPos ) ); + eeFloat tW = mTextCache->Font()->GetTextWidth(); + eeFloat tX = mAlignOffset.x + tW; - eeFloat tW = mTextCache->Font()->GetTextWidth(); - eeFloat tX = mAlignOffset.x + tW; - - mCurPos.x = tW; - mCurPos.y = (eeFloat)LineNum * (eeFloat)mTextCache->GetTextHeight(); - - if ( tX < 0.f ) - mAlignOffset.x = -( mAlignOffset.x + ( tW - mAlignOffset.x ) ); - else if ( tX > mSize.Width() - mPadding.Left - mPadding.Right ) - mAlignOffset.x = mSize.Width() - mPadding.Left - mPadding.Right - ( mAlignOffset.x + ( tW - mAlignOffset.x ) ); + mCurPos.x = tW; + mCurPos.y = (eeFloat)LineNum * (eeFloat)mTextCache->Font()->GetFontSize(); + if ( !mTextBuffer.SupportNewLine() ) { + if ( tX < 0.f ) + mAlignOffset.x = -( mAlignOffset.x + ( tW - mAlignOffset.x ) ); + else if ( tX > mSize.Width() - mPadding.Left - mPadding.Right ) + mAlignOffset.x = mSize.Width() - mPadding.Left - mPadding.Right - ( mAlignOffset.x + ( tW - mAlignOffset.x ) ); + } + } } void cUITextInput::SetTheme( cUITheme * Theme ) { @@ -168,4 +175,28 @@ const bool& cUITextInput::AllowEditing() const { return mAllowEditing; } +void cUITextInput::Text( const std::wstring& text ) { + cUITextBox::Text( text ); + + mTextBuffer.Buffer( text ); +} + +const std::wstring& cUITextInput::Text() { + return cUITextBox::Text(); +} + +void cUITextInput::Text( const std::string& text ) { + Text( stringTowstring( text ) ); +} + +void cUITextInput::ShrinkText( const Uint32& MaxWidth ) { + mTextCache->Text( mTextBuffer.Buffer() ); + + cUITextBox::ShrinkText( MaxWidth ); + + mTextBuffer.Buffer( mTextCache->Text() ); + + AlignFix(); +} + }} diff --git a/src/ui/cuitextinput.hpp b/src/ui/cuitextinput.hpp index f9bc9f15e..d56428a1f 100644 --- a/src/ui/cuitextinput.hpp +++ b/src/ui/cuitextinput.hpp @@ -40,13 +40,21 @@ class EE_API cUITextInput : public cUITextBox { void AllowEditing( const bool& allow ); const bool& AllowEditing() const; + + virtual const std::wstring& Text(); + + virtual void Text( const std::wstring& text ); + + virtual void Text( const std::string& text ); + + virtual void ShrinkText( const Uint32& MaxWidth ); protected: - cInputTextBuffer mTextBuffer; - bool mShowingWait; - eeFloat mWaitCursorTime; - eeVector2f mCurPos; - eeInt mCursorPos; - bool mAllowEditing; + cInputTextBuffer mTextBuffer; + bool mShowingWait; + eeFloat mWaitCursorTime; + eeVector2f mCurPos; + eeInt mCursorPos; + bool mAllowEditing; void ResetWaitCursor(); @@ -61,6 +69,8 @@ class EE_API cUITextInput : public cUITextBox { virtual Uint32 OnFocusLoss(); virtual Uint32 OnPressEnter(); + + virtual void OnCursorPosChange(); }; }} diff --git a/src/ui/cuitheme.cpp b/src/ui/cuitheme.cpp index 70ca04375..14bc125aa 100644 --- a/src/ui/cuitheme.cpp +++ b/src/ui/cuitheme.cpp @@ -55,6 +55,8 @@ static void LoadThemeElements() { UI_THEME_ELEMENTS.push_back( "menucheckbox_active" ); UI_THEME_ELEMENTS.push_back( "menucheckbox_inactive" ); UI_THEME_ELEMENTS.push_back( "menuarrow" ); + UI_THEME_ELEMENTS.push_back( "textedit" ); + UI_THEME_ELEMENTS.push_back( "textedit_box" ); } } diff --git a/src/ui/uihelper.hpp b/src/ui/uihelper.hpp index c029705f6..e6c3fa400 100644 --- a/src/ui/uihelper.hpp +++ b/src/ui/uihelper.hpp @@ -78,11 +78,18 @@ enum UI_CONTROL_TYPES { UI_TYPE_MENUITEM = 18, UI_TYPE_MENUCHECKBOX = 19, UI_TYPE_MENUSUBMENU = 20, - UI_TYPE_SPRITE = 21 + UI_TYPE_SPRITE = 21, + UI_TYPE_TEXTEDIT = 22 }; #define UI_TYPE_GET(X) ( 1 << (X) ) +enum UI_SCROLLBAR_MODE { + UI_SCROLLBAR_AUTO, + UI_SCROLLBAR_ALWAYS_ON, + UI_SCROLLBAR_ALWAYS_OFF +}; + }} #endif diff --git a/src/window/cinputtextbuffer.cpp b/src/window/cinputtextbuffer.cpp index 9ad3a0e08..0f674519a 100755 --- a/src/window/cinputtextbuffer.cpp +++ b/src/window/cinputtextbuffer.cpp @@ -68,7 +68,10 @@ void cInputTextBuffer::Update( EE_Event* Event ) { } else if ( ( c == KEY_RETURN || c == KEY_KP_ENTER ) && !cInput::instance()->MetaPressed() && !cInput::instance()->AltPressed() && !cInput::instance()->ControlPressed() ) { if ( SupportNewLine() && CanAdd() ) { InsertChar( mText, mPromptPos, L'\n' ); + mPromptPos++; + + mChangeSinceLastUpdate = true; } if ( mEnterCall.IsSet() )