📄 guitexteditctrl.cc
字号:
//delete anything highlighted
if ( mBlockEnd > 0 )
{
mTextBuffer.cut(mBlockStart, mBlockEnd-mBlockStart);
mCursorPos = mBlockStart;
mBlockStart = 0;
mBlockEnd = 0;
}
if ( ( mInsertOn && ( stringLen < mMaxStrLen ) ) ||
( !mInsertOn && ( mCursorPos < mMaxStrLen ) ) )
{
if ( mCursorPos == stringLen )
{
mTextBuffer.append(convertedChar);
mCursorPos++;
}
else
{
if ( mInsertOn )
{
mTextBuffer.insert(mCursorPos, convertedChar);
mCursorPos++;
}
else
{
mTextBuffer.cut(mCursorPos, 1);
mTextBuffer.insert(mCursorPos, convertedChar);
mCursorPos++;
}
}
}
else
playDeniedSound();
//reset the history index
mHistoryDirty = true;
//execute the console command if it exists
execConsoleCallback();
return true;
}
//not handled - pass the event to it's parent
// Or eat it if that's appropriate.
if (mSinkAllKeyEvents)
return true;
return Parent::onKeyDown( event );
}
void GuiTextEditCtrl::setFirstResponder()
{
Parent::setFirstResponder();
Platform::enableKeyboardTranslation();
#ifdef TGE_RPG
#endif
}
void GuiTextEditCtrl::onLoseFirstResponder()
{
Platform::disableKeyboardTranslation();
//first, update the history
updateHistory( &mTextBuffer, true );
//execute the validate command
if ( mValidateCommand[0] )
Con::evaluate( mValidateCommand, false );
// Redraw the control:
setUpdate();
}
#ifdef TGE_RPG
void GuiTextEditCtrl::clearFirstResponder()
{
Parent::clearFirstResponder();
Platform::disableKeyboardTranslation();
}
#endif
void GuiTextEditCtrl::parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent)
{
Parent::parentResized( oldParentExtent, newParentExtent );
mTextOffsetReset = true;
}
void GuiTextEditCtrl::onRender(Point2I offset, const RectI & /*updateRect*/)
{
RectI ctrlRect( offset, mBounds.extent );
//if opaque, fill the update rect with the fill color
if ( mProfile->mOpaque )
dglDrawRectFill( ctrlRect, mProfile->mFillColor );
//if there's a border, draw the border
if ( mProfile->mBorder )
renderBorder( ctrlRect, mProfile );
drawText( ctrlRect, isFirstResponder() );
}
void GuiTextEditCtrl::onPreRender()
{
if ( isFirstResponder() )
{
U32 timeElapsed = Platform::getVirtualMilliseconds() - mTimeLastCursorFlipped;
mNumFramesElapsed++;
if ( ( timeElapsed > 500 ) && ( mNumFramesElapsed > 3 ) )
{
mCursorOn = !mCursorOn;
mTimeLastCursorFlipped = Platform::getVirtualMilliseconds();
mNumFramesElapsed = 0;
setUpdate();
}
//update the cursor if the text is scrolling
if ( mDragHit )
{
if ( ( mScrollDir < 0 ) && ( mCursorPos > 0 ) )
mCursorPos--;
else if ( ( mScrollDir > 0 ) && ( mCursorPos < (S32) mTextBuffer.length() ) )
mCursorPos++;
}
}
}
void GuiTextEditCtrl::drawText( const RectI &drawRect, bool isFocused )
{
StringBuffer textBuffer;
Point2I drawPoint = drawRect.point;
Point2I paddingLeftTop, paddingRightBottom;
// Just a little sanity.
if(mCursorPos > mTextBuffer.length())
mCursorPos = mTextBuffer.length();
// Apply password masking (make the masking char optional perhaps?)
if(mPasswordText)
{
for(U32 i = 0; i<mTextBuffer.length()-1; i++)
textBuffer.append(StringBuffer(mPasswordMask));
}
else
{
// Or else just copy it over.
textBuffer.set(&mTextBuffer);
}
paddingLeftTop.set(( mProfile->mTextOffset.x != 0 ? mProfile->mTextOffset.x : 3 ), mProfile->mTextOffset.y);
paddingRightBottom = paddingLeftTop;
// Center vertically:
drawPoint.y += ( ( drawRect.extent.y - paddingLeftTop.y - paddingRightBottom.y - mFont->getHeight() ) / 2 ) + paddingLeftTop.y;
// Align horizontally:
S32 textWidth;
{
FrameTemp<UTF8> widthTemp(textBuffer.length()*3+1);
textBuffer.get(widthTemp, textBuffer.length()*3+1);
textWidth = mFont->getStrWidth( widthTemp );
}
if ( drawRect.extent.x - paddingLeftTop.x > textWidth )
{
switch( mProfile->mAlignment )
{
case GuiControlProfile::RightJustify:
drawPoint.x += ( drawRect.extent.x - textWidth - paddingRightBottom.x );
break;
case GuiControlProfile::CenterJustify:
drawPoint.x += ( ( drawRect.extent.x - textWidth ) / 2 );
break;
default:
case GuiControlProfile::LeftJustify :
drawPoint.x += paddingLeftTop.x;
break;
}
}
else
drawPoint.x += paddingLeftTop.x;
ColorI fontColor = mActive ? mProfile->mFontColor : mProfile->mFontColorNA;
// now draw the text
Point2I cursorStart, cursorEnd;
mTextOffset.y = drawPoint.y;
if ( mTextOffsetReset )
{
mTextOffset.x = drawPoint.x;
mTextOffsetReset = false;
}
if ( drawRect.extent.x - paddingLeftTop.x > textWidth )
mTextOffset.x = drawPoint.x;
else
{
// Alignment affects large text
if ( mProfile->mAlignment == GuiControlProfile::RightJustify
|| mProfile->mAlignment == GuiControlProfile::CenterJustify )
{
if ( mTextOffset.x + textWidth < (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x)
mTextOffset.x = (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x - textWidth;
}
}
// calculate the cursor
if ( isFocused )
{
// Where in the string are we?
StringBuffer preCursor = mTextBuffer.substring(0, mCursorPos);
S32 cursorOffset=0, charWidth=0;
UTF16 tempChar = mTextBuffer.getChar(mCursorPos);
// Alright, we want to terminate things momentarily.
if(mCursorPos > 0)
{
FrameTemp<UTF8> cursorTemp(preCursor.length()*3+1);
preCursor.get(cursorTemp, preCursor.length()*3+1);
cursorOffset = mFont->getStrWidth(cursorTemp);
}
else
cursorOffset = 0;
if ( tempChar )
charWidth = mFont->getCharWidth( tempChar );
else
charWidth = paddingRightBottom.x;
if( mTextOffset.x + cursorOffset + charWidth >= (drawRect.point.x + drawRect.extent.x) - paddingLeftTop.x )
{
// Cursor somewhere beyond the textcontrol,
// skip forward roughly 25% of the total width (if possible)
S32 skipForward = drawRect.extent.x / 4;
if ( cursorOffset + skipForward > textWidth )
mTextOffset.x = (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x - textWidth;
else
mTextOffset.x -= skipForward;
}
else if( mTextOffset.x + cursorOffset < drawRect.point.x + paddingLeftTop.x )
{
// Cursor somewhere before the textcontrol
// skip backward roughly 25% of the total width (if possible)
S32 skipBackward = drawRect.extent.x / 4;
if ( cursorOffset - skipBackward < 0 )
mTextOffset.x = drawRect.point.x + paddingLeftTop.x;
else
mTextOffset.x += skipBackward;
}
cursorStart.x = mTextOffset.x + cursorOffset;
cursorEnd.x = cursorStart.x;
S32 cursorHeight = mFont->getHeight();
if ( cursorHeight < drawRect.extent.y )
{
cursorStart.y = drawPoint.y;
cursorEnd.y = cursorStart.y + cursorHeight;
}
else
{
cursorStart.y = drawRect.point.y;
cursorEnd.y = cursorStart.y + drawRect.extent.y;
}
}
//draw the text
if ( !isFocused )
mBlockStart = mBlockEnd = 0;
//also verify the block start/end
if ((mBlockStart > textBuffer.length() || (mBlockEnd > textBuffer.length()) || (mBlockStart > mBlockEnd)))
mBlockStart = mBlockEnd = 0;
UTF16 temp;
Point2I tempOffset = mTextOffset;
//draw the portion before the highlight
if ( mBlockStart > 0 )
{
StringBuffer preBuffer = textBuffer.substring(0, mBlockStart);
FrameTemp<UTF8> preString(preBuffer.length()*3+1);
preBuffer.get(preString, preBuffer.length()*3+1);
dglSetBitmapModulation( fontColor );
dglDrawText( mFont, tempOffset, preString, mProfile->mFontColors );
tempOffset.x += mFont->getStrWidth( (const UTF8*)preString );
}
//draw the hilighted portion
if ( mBlockEnd > 0 )
{
StringBuffer highlightBuff = mTextBuffer.substring(mBlockStart, mBlockEnd-mBlockStart);
FrameTemp<UTF8> highlightTemp(highlightBuff.length()*3 + 1);
highlightBuff.get(highlightTemp, highlightBuff.length()*3 + 1);
S32 highlightWidth = mFont->getStrWidth( highlightTemp );
dglDrawRectFill( Point2I( tempOffset.x, drawRect.point.y ),
Point2I( tempOffset.x + highlightWidth, drawRect.point.y + drawRect.extent.y - 1),
mProfile->mFillColorHL );
dglSetBitmapModulation( mProfile->mFontColorHL );
dglDrawText( mFont, tempOffset, highlightTemp, mProfile->mFontColors );
tempOffset.x += highlightWidth;
}
//draw the portion after the highlite
if(mBlockEnd < mTextBuffer.length())
{
StringBuffer finalBuff = mTextBuffer.substring(mBlockEnd, mTextBuffer.length() - mBlockEnd);
FrameTemp<UTF8> finalTemp(finalBuff.length()*3 + 1);
finalBuff.get(finalTemp, finalBuff.length()*3 + 1);
dglSetBitmapModulation( fontColor );
dglDrawText( mFont, tempOffset, finalTemp, mProfile->mFontColors );
}
#if TGE_RPG
mCursorOffset = cursorStart - mBounds.point;
#endif
//draw the cursor
if ( isFocused && mCursorOn )
dglDrawLine( cursorStart, cursorEnd, mProfile->mCursorColor );
}
bool GuiTextEditCtrl::hasText()
{
return (mTextBuffer.length());
}
void GuiTextEditCtrl::playDeniedSound()
{
if ( mDeniedSound )
{
AUDIOHANDLE handle = alxCreateSource( mDeniedSound );
alxPlay( handle );
}
}
bool GuiTextEditCtrl::initCursors()
{
if ( mEditCursor == NULL )
{
SimObject *obj;
obj = Sim::findObject("TextEditCursor");
mEditCursor = dynamic_cast<GuiCursor*>(obj);
return( mEditCursor != NULL );
}
else
return(true);
}
void GuiTextEditCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent)
{
showCursor = true;
if( initCursors() )
{
Point2I mousePos = lastGuiEvent.mousePoint;
RectI winRect = mBounds;
winRect.point = localToGlobalCoord( winRect.point );
if( winRect.pointInRect( mousePos ) )
cursor = mEditCursor;
else
cursor = NULL;
}
}
const char *GuiTextEditCtrl::getScriptValue()
{
FrameTemp<UTF8> temp(mTextBuffer.length() * 3 + 1);
mTextBuffer.get(temp, mTextBuffer.length() * 3 + 1);
return StringTable->insert((const char*)(UTF8*)temp);
}
void GuiTextEditCtrl::setScriptValue(const char *value)
{
mTextBuffer.set(value);
mCursorPos = mTextBuffer.length() - 1;
}
ConsoleMethod( GuiTextEditCtrl, getText, const char*, 2, 2, "textEditCtrl.getText()" )
{
argc; argv;
if( !object->hasText() )
return StringTable->insert("");
char *retBuffer = Con::getReturnBuffer( GuiTextEditCtrl::MAX_STRING_LENGTH );
object->getText( retBuffer );
return retBuffer;
}
ConsoleMethod( GuiTextEditCtrl, getCursorPos, S32, 2, 2, "textEditCtrl.getCursorPos()" )
{
argc; argv;
return( object->getCursorPos() );
}
ConsoleMethod( GuiTextEditCtrl, setCursorPos, void, 3, 3, "textEditCtrl.setCursorPos( newPos )" )
{
argc;
object->reallySetCursorPos( dAtoi( argv[2] ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -