mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-07-17 08:12:59 +03:00
Added support for string selection, copy and paste for cUITextBox, cUITextInput and cUITextEdit.
305 lines
7.1 KiB
C++
305 lines
7.1 KiB
C++
#include <eepp/ui/cuitextinput.hpp>
|
|
#include <eepp/ui/cuimanager.hpp>
|
|
#include <eepp/window/cengine.hpp>
|
|
#include <eepp/graphics/renderer/cgl.hpp>
|
|
#include <eepp/graphics/cprimitives.hpp>
|
|
#include <eepp/graphics/cfont.hpp>
|
|
#include <eepp/graphics/ctextcache.hpp>
|
|
|
|
namespace EE { namespace UI {
|
|
|
|
cUITextInput::cUITextInput( const cUITextInput::CreateParams& Params ) :
|
|
cUITextBox( Params ),
|
|
mCursorPos(0),
|
|
mAllowEditing( true ),
|
|
mShowingWait( true )
|
|
{
|
|
mTextBuffer.Start();
|
|
mTextBuffer.Active( false );
|
|
mTextBuffer.SupportFreeEditing( Params.SupportFreeEditing );
|
|
mTextBuffer.MaxLength( Params.MaxLength );
|
|
mTextBuffer.SetReturnCallback( cb::Make0( this, &cUITextInput::PrivOnPressEnter ) );
|
|
|
|
ApplyDefaultTheme();
|
|
}
|
|
|
|
cUITextInput::~cUITextInput() {
|
|
}
|
|
|
|
Uint32 cUITextInput::Type() const {
|
|
return UI_TYPE_TEXTINPUT;
|
|
}
|
|
|
|
bool cUITextInput::IsType( const Uint32& type ) const {
|
|
return cUITextInput::Type() == type ? true : cUITextBox::IsType( type );
|
|
}
|
|
|
|
void cUITextInput::Update() {
|
|
if ( IsMouseOverMeOrChilds() ) {
|
|
cUIManager::instance()->SetCursor( EE_CURSOR_IBEAM );
|
|
}
|
|
|
|
cUITextBox::Update();
|
|
|
|
if ( mTextBuffer.ChangedSinceLastUpdate() ) {
|
|
eeVector2f offSet = mAlignOffset;
|
|
|
|
cUITextBox::Text( mTextBuffer.Buffer() );
|
|
|
|
UpdateText();
|
|
|
|
mAlignOffset = offSet;
|
|
|
|
ResetWaitCursor();
|
|
|
|
AlignFix();
|
|
|
|
mCursorPos = mTextBuffer.CurPos();
|
|
|
|
mTextBuffer.ChangedSinceLastUpdate( false );
|
|
|
|
return;
|
|
}
|
|
|
|
if ( mCursorPos != mTextBuffer.CurPos() ) {
|
|
AlignFix();
|
|
mCursorPos = mTextBuffer.CurPos();
|
|
OnCursorPosChange();
|
|
}
|
|
}
|
|
|
|
void cUITextInput::OnCursorPosChange() {
|
|
SendCommonEvent( cUIEvent::EventOnCursorPosChange );
|
|
}
|
|
|
|
void cUITextInput::DrawWaitingCursor() {
|
|
if ( mVisible && mTextBuffer.Active() && mTextBuffer.SupportFreeEditing() ) {
|
|
mWaitCursorTime += cUIManager::instance()->Elapsed().AsMilliseconds();
|
|
|
|
if ( mShowingWait ) {
|
|
bool disableSmooth = mShowingWait && GLi->IsLineSmooth();
|
|
|
|
if ( disableSmooth )
|
|
GLi->LineSmooth( false );
|
|
|
|
cPrimitives P;
|
|
P.SetColor( mFontColor );
|
|
|
|
eeFloat CurPosX = mScreenPos.x + mAlignOffset.x + mCurPos.x + 1 + mPadding.Left;
|
|
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;
|
|
|
|
P.DrawLine( eeLine2f( eeVector2f( CurPosX, CurPosY ), eeVector2f( CurPosX, CurPosY + mTextCache->Font()->GetFontHeight() ) ) );
|
|
|
|
if ( disableSmooth )
|
|
GLi->LineSmooth( true );
|
|
}
|
|
|
|
if ( mWaitCursorTime >= 500.f ) {
|
|
mShowingWait = !mShowingWait;
|
|
mWaitCursorTime = 0.f;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cUITextInput::Draw() {
|
|
cUITextBox::Draw();
|
|
|
|
DrawWaitingCursor();
|
|
}
|
|
|
|
Uint32 cUITextInput::OnFocus() {
|
|
cUIControlAnim::OnFocus();
|
|
|
|
if ( mAllowEditing ) {
|
|
mTextBuffer.Active( true );
|
|
|
|
ResetWaitCursor();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
Uint32 cUITextInput::OnFocusLoss() {
|
|
mTextBuffer.Active( false );
|
|
return cUITextBox::OnFocusLoss();
|
|
}
|
|
|
|
Uint32 cUITextInput::OnPressEnter() {
|
|
SendCommonEvent( cUIEvent::EventOnPressEnter );
|
|
return 0;
|
|
}
|
|
|
|
void cUITextInput::PrivOnPressEnter() {
|
|
OnPressEnter();
|
|
}
|
|
|
|
void cUITextInput::PushIgnoredChar( const Uint32& ch ) {
|
|
mTextBuffer.PushIgnoredChar( ch );
|
|
}
|
|
|
|
void cUITextInput::ResetWaitCursor() {
|
|
mShowingWait = true;
|
|
mWaitCursorTime = 0.f;
|
|
}
|
|
|
|
void cUITextInput::AlignFix() {
|
|
if ( FontHAlignGet( Flags() ) == UI_HALIGN_LEFT ) {
|
|
Uint32 NLPos = 0;
|
|
Uint32 LineNum = mTextBuffer.GetCurPosLinePos( NLPos );
|
|
|
|
mTextCache->Font()->SetText( mTextBuffer.Buffer().substr( NLPos, mTextBuffer.CurPos() - NLPos ) );
|
|
|
|
eeFloat tW = mTextCache->Font()->GetTextWidth();
|
|
eeFloat tX = mAlignOffset.x + tW;
|
|
|
|
mCurPos.x = tW;
|
|
mCurPos.y = (eeFloat)LineNum * (eeFloat)mTextCache->Font()->GetFontHeight();
|
|
|
|
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 ) {
|
|
cUIControl::SetThemeControl( Theme, "textinput" );
|
|
|
|
AutoPadding();
|
|
AutoSize();
|
|
}
|
|
|
|
void cUITextInput::AutoSize() {
|
|
if ( mFlags & UI_AUTO_SIZE ) {
|
|
Size( mSize.x, GetSkinSize().Height() );
|
|
}
|
|
}
|
|
|
|
void cUITextInput::AutoPadding() {
|
|
if ( mFlags & UI_AUTO_PADDING ) {
|
|
mPadding = MakePadding( true, true, false, false );
|
|
}
|
|
}
|
|
|
|
cInputTextBuffer * cUITextInput::GetInputTextBuffer() {
|
|
return &mTextBuffer;
|
|
}
|
|
|
|
void cUITextInput::AllowEditing( const bool& allow ) {
|
|
mAllowEditing = allow;
|
|
|
|
if ( !mAllowEditing && mTextBuffer.Active() )
|
|
mTextBuffer.Active( false );
|
|
}
|
|
|
|
const bool& cUITextInput::AllowEditing() const {
|
|
return mAllowEditing;
|
|
}
|
|
|
|
void cUITextInput::Text( const String& text ) {
|
|
cUITextBox::Text( text );
|
|
|
|
mTextBuffer.Buffer( text );
|
|
|
|
mTextBuffer.CursorToEnd();
|
|
}
|
|
|
|
const String& cUITextInput::Text() {
|
|
return cUITextBox::Text();
|
|
}
|
|
|
|
void cUITextInput::ShrinkText( const Uint32& MaxWidth ) {
|
|
mTextCache->Text( mTextBuffer.Buffer() );
|
|
|
|
cUITextBox::ShrinkText( MaxWidth );
|
|
|
|
mTextBuffer.Buffer( mTextCache->Text() );
|
|
|
|
AlignFix();
|
|
}
|
|
|
|
void cUITextInput::UpdateText() {
|
|
}
|
|
|
|
Uint32 cUITextInput::OnMouseClick( const eeVector2i& Pos, const Uint32 Flags ) {
|
|
if ( Flags & EE_BUTTON_LMASK ) {
|
|
eeVector2i controlPos( Pos );
|
|
WorldToControl( controlPos );
|
|
|
|
Int32 curPos = mTextCache->Font()->FindClosestCursorPosFromPoint( mTextCache->Text(), controlPos );
|
|
|
|
if ( -1 != curPos ) {
|
|
mTextBuffer.CurPos( curPos );
|
|
ResetWaitCursor();
|
|
}
|
|
}
|
|
|
|
return cUITextBox::OnMouseClick( Pos, Flags );
|
|
}
|
|
|
|
Uint32 cUITextInput::OnMouseDoubleClick( const eeVector2i& Pos, const Uint32 Flags ) {
|
|
cUITextBox::OnMouseDoubleClick( Pos, Flags );
|
|
|
|
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) && mSelCurEnd != -1 ) {
|
|
mTextBuffer.CurPos( mSelCurEnd );
|
|
ResetWaitCursor();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
Uint32 cUITextInput::OnMouseDown( const eeVector2i& Pos, const Uint32 Flags ) {
|
|
cUITextBox::OnMouseDown( Pos, Flags );
|
|
|
|
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) && mSelCurEnd != -1 ) {
|
|
mTextBuffer.CurPos( mSelCurEnd );
|
|
ResetWaitCursor();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
Uint32 cUITextInput::OnMouseExit( const eeVector2i& Pos, const Uint32 Flags ) {
|
|
cUIControl::OnMouseExit( Pos, Flags );
|
|
|
|
cUIManager::instance()->SetCursor( EE_CURSOR_ARROW );
|
|
|
|
return 1;
|
|
}
|
|
|
|
Uint32 cUITextInput::OnKeyDown( const cUIEventKey & Event ) {
|
|
cUITextBox::OnKeyDown( Event );
|
|
|
|
if ( IsTextSelectionEnabled() ) {
|
|
if ( ( Event.Mod() & KEYMOD_LCTRL ) && Event.KeyCode() == KEY_A && 0 == mSelCurInit && (Int32)mTextCache->Text().size() == mSelCurEnd ) {
|
|
mTextBuffer.CurPos( mSelCurEnd );
|
|
ResetWaitCursor();
|
|
}
|
|
|
|
if ( mSelCurInit >= 0 && mSelCurInit != mSelCurEnd ) {
|
|
if ( ( ( Event.Mod() & KEYMOD_LCTRL ) && ( Event.KeyCode() == KEY_X || Event.KeyCode() == KEY_V ) ) ) {
|
|
Int32 init = eemin( mSelCurInit, mSelCurEnd );
|
|
Int32 end = eemax( mSelCurInit, mSelCurEnd );
|
|
String iniStr( mTextCache->Text().substr( 0, init ) );
|
|
String endStr( mTextCache->Text().substr( end ) );
|
|
|
|
Text( iniStr + endStr );
|
|
|
|
mTextBuffer.CurPos( mSelCurInit );
|
|
ResetWaitCursor();
|
|
|
|
mSelCurInit = mSelCurEnd = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
}}
|