829 lines
23 KiB
C++
829 lines
23 KiB
C++
// Copyright (C) 2007 Id Software, Inc.
|
|
//
|
|
|
|
|
|
#include "../precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "../../framework/KeyInput.h"
|
|
#include "../../sys/sys_local.h"
|
|
|
|
#include "UIWindow.h"
|
|
#include "UserInterfaceLocal.h"
|
|
#include "UIEditW.h"
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// sdUIEditW
|
|
//
|
|
//===============================================================
|
|
|
|
SD_UI_IMPLEMENT_CLASS( sdUIEditW, sdUIWindow )
|
|
|
|
SD_UI_PUSH_CLASS_TAG( sdUIEditW )
|
|
const char* sdUIEditW::eventNames[ EE_NUM_EVENTS - WE_NUM_EVENTS ] = {
|
|
SD_UI_EVENT_TAG( "onInputFailed", "", "Called if typing any characters that breaks the EF_ALLOW_DECIMAL/EF_INTEGERS_ONLY flags." ),
|
|
};
|
|
SD_UI_POP_CLASS_TAG
|
|
|
|
idHashMap< sdUITemplateFunction< sdUIEditW >* > sdUIEditW::editFunctions;
|
|
const char sdUITemplateFunctionInstance_IdentifierEditW[] = "sdUIEditWFunction";
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::sdUIEditW
|
|
============
|
|
*/
|
|
sdUIEditW::sdUIEditW() {
|
|
helper.Init( this );
|
|
|
|
scriptState.GetProperties().RegisterProperty( "editText", editText );
|
|
scriptState.GetProperties().RegisterProperty( "scrollAmount", scrollAmount );
|
|
scriptState.GetProperties().RegisterProperty( "scrollAmountMax", scrollAmountMax );
|
|
scriptState.GetProperties().RegisterProperty( "lineHeight", lineHeight );
|
|
|
|
scriptState.GetProperties().RegisterProperty( "maxTextLength", maxTextLength );
|
|
scriptState.GetProperties().RegisterProperty( "readOnly", readOnly );
|
|
scriptState.GetProperties().RegisterProperty( "password", password );
|
|
|
|
scriptState.GetProperties().RegisterProperty( "cursor", cursorName );
|
|
scriptState.GetProperties().RegisterProperty( "overwriteCursor", overwriteCursorName );
|
|
|
|
scriptState.GetProperties().RegisterProperty( "IMEFillColor", IMEFillColor );
|
|
scriptState.GetProperties().RegisterProperty( "IMEBorderColor", IMEBorderColor );
|
|
scriptState.GetProperties().RegisterProperty( "IMESelectionColor", IMESelectionColor );
|
|
scriptState.GetProperties().RegisterProperty( "IMETextColor", IMETextColor );
|
|
|
|
textAlignment.SetIndex( 0, TA_LEFT );
|
|
maxTextLength = 0;
|
|
readOnly = 0.0f;
|
|
password = 0.0f;
|
|
textOffset = idVec2( 2.0f, 0.0f );
|
|
|
|
scrollAmount = vec2_zero;
|
|
scrollAmountMax = 0.0f;
|
|
lineHeight = 0.0f;
|
|
|
|
scrollAmountMax.SetReadOnly( true );
|
|
lineHeight.SetReadOnly( true );
|
|
|
|
UI_ADD_WSTR_CALLBACK( editText, sdUIEditW, OnEditTextChanged )
|
|
UI_ADD_FLOAT_CALLBACK( readOnly, sdUIEditW, OnReadOnlyChanged )
|
|
UI_ADD_FLOAT_CALLBACK( flags, sdUIEditW, OnFlagsChanged )
|
|
UI_ADD_STR_CALLBACK( cursorName, sdUIEditW, OnCursorNameChanged )
|
|
UI_ADD_STR_CALLBACK( overwriteCursorName, sdUIEditW, OnOverwriteCursorNameChanged )
|
|
|
|
SetWindowFlag( WF_ALLOW_FOCUS );
|
|
SetWindowFlag( WF_CLIP_TO_RECT );
|
|
|
|
drawIME = false;
|
|
composing = false;
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::InitProperties
|
|
============
|
|
*/
|
|
void sdUIEditW::InitProperties() {
|
|
sdUIWindow::InitProperties();
|
|
cursorName = "editcursor";
|
|
overwriteCursorName = "editcursor_overwrite";
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::~sdUIEditW
|
|
============
|
|
*/
|
|
sdUIEditW::~sdUIEditW() {
|
|
DisconnectGlobalCallbacks();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::FindFunction
|
|
============
|
|
*/
|
|
const sdUITemplateFunction< sdUIEditW >* sdUIEditW::FindFunction( const char* name ) {
|
|
sdUITemplateFunction< sdUIEditW >** ptr;
|
|
return editFunctions.Get( name, &ptr ) ? *ptr : NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::GetFunction
|
|
============
|
|
*/
|
|
sdUIFunctionInstance* sdUIEditW::GetFunction( const char* name ) {
|
|
const sdUITemplateFunction< sdUIEditW >* function = sdUIEditW::FindFunction( name );
|
|
if ( !function ) {
|
|
return sdUIWindow::GetFunction( name );
|
|
}
|
|
|
|
return new sdUITemplateFunctionInstance< sdUIEditW, sdUITemplateFunctionInstance_IdentifierEditW >( this, function );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::RunNamedMethod
|
|
============
|
|
*/
|
|
bool sdUIEditW::RunNamedMethod( const char* name, sdUIFunctionStack& stack ) {
|
|
const sdUITemplateFunction< sdUIEditW >* func = sdUIEditW::FindFunction( name );
|
|
if ( !func ) {
|
|
return sdUIWindow::RunNamedMethod( name, stack );
|
|
}
|
|
|
|
CALL_MEMBER_FN_PTR( this, func->GetFunction() )( stack );
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::DrawLocal
|
|
============
|
|
*/
|
|
void sdUIEditW::DrawLocal() {
|
|
if ( PreDraw() ) {
|
|
DrawBackground( cachedClientRect );
|
|
|
|
deviceContext->PushClipRect( GetDrawRect() );
|
|
|
|
helper.DrawText( foreColor );
|
|
helper.DrawLocal();
|
|
|
|
deviceContext->PopClipRect();
|
|
|
|
// border
|
|
if ( borderWidth > 0.0f ) {
|
|
deviceContext->DrawClippedBox( cachedClientRect.x, cachedClientRect.y, cachedClientRect.z, cachedClientRect.w, borderWidth, borderColor );
|
|
}
|
|
|
|
// Can draw the IME elements
|
|
drawIME = true;
|
|
}
|
|
|
|
PostDraw();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::DrawLocal
|
|
============
|
|
*/
|
|
void sdUIEditW::FinalDraw() {
|
|
if ( drawIME ) {
|
|
drawIME = false;
|
|
|
|
// Render the IME elements
|
|
if ( sys->IME().LangSupportsIME() && GetUI()->IsFocused( this ) ) {
|
|
// Draw the input locale indicator
|
|
DrawIndicator();
|
|
|
|
// Display the composition string
|
|
//DrawComposition();
|
|
|
|
if ( sys->IME().IsReadingWindowActive() ) {
|
|
// Reading window
|
|
DrawCandidateReadingWindow( true );
|
|
} else if ( sys->IME().IsCandidateListActive() ) {
|
|
DrawCandidateReadingWindow( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
sdUIWindow::FinalDraw();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::PostEvent
|
|
============
|
|
*/
|
|
bool sdUIEditW::PostEvent( const sdSysEvent* event ) {
|
|
if ( !IsVisible() || !ParentsAllowEventPosting() ) {
|
|
return false;
|
|
}
|
|
|
|
bool retVal = sdUIWindow::PostEvent( event );
|
|
|
|
if ( event->IsIMEEvent() ) {
|
|
switch ( event->GetIMEEvent() ) {
|
|
case IMEV_COMPOSITION_START:
|
|
if ( !readOnly ) {
|
|
// enable composition mode
|
|
composing = true;
|
|
helper.QueueEvent( sdUIEditHelper< sdUIEditW, idWStr, wchar_t >::sdUIEditEvent::EE_COMPOSITION_CURSOR_SET );
|
|
helper.InsertText( L"" ); // makes sure that the current selection gets cleared out
|
|
compositionString.Clear();
|
|
return true;
|
|
}
|
|
break;
|
|
case IMEV_COMPOSITION_END:
|
|
composing = false;
|
|
compositionString.Clear();
|
|
return true;
|
|
case IMEV_COMPOSITION_UPDATE:
|
|
if ( composing ) {
|
|
// schedule a recalculation of text wrapping etc
|
|
compositionString = event->GetCompositionString();
|
|
MakeLayoutDirty();
|
|
return true;
|
|
}
|
|
break;
|
|
case IMEV_COMPOSITION_COMMIT:
|
|
if ( !readOnly ) {
|
|
int len = idWStr::Length( event->GetCompositionString() );
|
|
|
|
size_t dataSize = ( len + 1 ) * sizeof( wchar_t );
|
|
void* data = Mem_Alloc( dataSize );
|
|
::memcpy( data, event->GetCompositionString(), dataSize );
|
|
helper.QueueEvent( sdUIEditHelper< sdUIEditW, idWStr, wchar_t >::sdUIEditEvent::EE_COMPOSITION_COMMIT, 0, 0, 0, 0, 0, dataSize, data );
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return helper.PostEvent( retVal, event );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_ClearText
|
|
============
|
|
*/
|
|
void sdUIEditW::Script_ClearText( sdUIFunctionStack& stack ) {
|
|
ClearText();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_ClearText
|
|
============
|
|
*/
|
|
const wchar_t* sdUIEditW::GetCursorText() const {
|
|
return ( compositionString.c_str() );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::InitFunctions
|
|
============
|
|
*/
|
|
#pragma inline_depth( 0 )
|
|
#pragma optimize( "", off )
|
|
SD_UI_PUSH_CLASS_TAG( sdUIEditW )
|
|
void sdUIEditW::InitFunctions() {
|
|
SD_UI_FUNC_TAG( clearText, "Clear all window text." )
|
|
SD_UI_END_FUNC_TAG
|
|
editFunctions.Set( "clearText", new sdUITemplateFunction< sdUIEditW >( 'v', "", &sdUIEditW::Script_ClearText ) );
|
|
|
|
SD_UI_FUNC_TAG( isWhitespace, "Check whitespaces, ignores all color codes." )
|
|
SD_UI_FUNC_RETURN_PARM( float, "True if it is empty or contain only whitespaces." )
|
|
SD_UI_END_FUNC_TAG
|
|
editFunctions.Set( "isWhitespace", new sdUITemplateFunction< sdUIEditW >( 'f', "", &sdUIEditW::Script_IsWhitespace ) );
|
|
|
|
SD_UI_FUNC_TAG( insertText, "Insert text into the edit box." )
|
|
SD_UI_FUNC_PARM( wstring, "text", "Text to insert." )
|
|
SD_UI_END_FUNC_TAG
|
|
editFunctions.Set( "insertText", new sdUITemplateFunction< sdUIEditW >( 'v', "w", &sdUIEditW::Script_InsertText ) );
|
|
|
|
SD_UI_FUNC_TAG( surroundSelection, "Select certain substring." )
|
|
SD_UI_FUNC_PARM( wstring, "prefix", "Prefix to selection text." )
|
|
SD_UI_FUNC_PARM( wstring, "suffix", "Suffix to selection text." )
|
|
SD_UI_END_FUNC_TAG
|
|
editFunctions.Set( "surroundSelection", new sdUITemplateFunction< sdUIEditW >( 'v', "ww", &sdUIEditW::Script_SurroundSelection ) );
|
|
|
|
SD_UI_FUNC_TAG( anySelected, "Check if any of the edit text is selected." )
|
|
SD_UI_FUNC_RETURN_PARM( float, "True if any text has been selected." )
|
|
SD_UI_END_FUNC_TAG
|
|
editFunctions.Set( "anySelected", new sdUITemplateFunction< sdUIEditW >( 'f', "", &sdUIEditW::Script_AnySelected ) );
|
|
|
|
SD_UI_FUNC_TAG( selectAll, "Select all text in the edit box." )
|
|
SD_UI_END_FUNC_TAG
|
|
editFunctions.Set( "selectAll", new sdUITemplateFunction< sdUIEditW >( 'v', "", &sdUIEditW::Script_SelectAll ) );
|
|
|
|
SD_UI_PUSH_GROUP_TAG( "Edit Flags" )
|
|
|
|
SD_UI_ENUM_TAG( EF_INTEGERS_ONLY, "Accept only integer numbers in edit box." )
|
|
sdDeclGUI::AddDefine( va( "EF_INTEGERS_ONLY %d", EF_INTEGERS_ONLY ) );
|
|
SD_UI_ENUM_TAG( EF_ALLOW_DECIMAL, "Allow decimal numbers to be typed." )
|
|
sdDeclGUI::AddDefine( va( "EF_ALLOW_DECIMAL %d", EF_ALLOW_DECIMAL ) );
|
|
|
|
SD_UI_POP_GROUP_TAG
|
|
}
|
|
SD_UI_POP_CLASS_TAG
|
|
#pragma optimize( "", on )
|
|
#pragma inline_depth()
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::ApplyLayout
|
|
============
|
|
*/
|
|
void sdUIEditW::ApplyLayout() {
|
|
bool needLayout = windowState.recalculateLayout;
|
|
sdUIWindow::ApplyLayout();
|
|
helper.ApplyLayout();
|
|
if ( needLayout ) {
|
|
helper.TextChanged();
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::ClearText
|
|
============
|
|
*/
|
|
void sdUIEditW::ClearText() {
|
|
helper.ClearText();
|
|
editText = L"";
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnEditTextChanged
|
|
============
|
|
*/
|
|
void sdUIEditW::OnEditTextChanged( const idWStr& oldValue, const idWStr& newValue ) {
|
|
MakeLayoutDirty();
|
|
helper.MakeTextDirty();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnCursorNameChanged
|
|
============
|
|
*/
|
|
void sdUIEditW::OnCursorNameChanged( const idStr& oldValue, const idStr& newValue ) {
|
|
GetUI()->LookupMaterial( newValue, cursor.mi, &cursor.width, &cursor.height );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnOverwriteCursorNameChanged
|
|
============
|
|
*/
|
|
void sdUIEditW::OnOverwriteCursorNameChanged( const idStr& oldValue, const idStr& newValue ) {
|
|
GetUI()->LookupMaterial( newValue, overwriteCursor.mi, &overwriteCursor.width, &overwriteCursor.height );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::EndLevelLoad
|
|
============
|
|
*/
|
|
void sdUIEditW::EndLevelLoad() {
|
|
sdUserInterfaceLocal::SetupMaterialInfo( cursor.mi, &cursor.width, &cursor.height );
|
|
sdUserInterfaceLocal::SetupMaterialInfo( overwriteCursor.mi, &overwriteCursor.width, &overwriteCursor.height );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::EnumerateEvents
|
|
============
|
|
*/
|
|
void sdUIEditW::EnumerateEvents( const char* name, const idList<unsigned short>& flags, idList< sdUIEventInfo >& events, const idTokenCache& tokenCache ) {
|
|
if ( !idStr::Icmp( name, "onInputFailed" ) ) {
|
|
events.Append( sdUIEventInfo( EE_INPUT_FAILED, 0 ) );
|
|
return;
|
|
}
|
|
sdUIWindow::EnumerateEvents( name, flags, events, tokenCache );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnReadOnlyChanged
|
|
============
|
|
*/
|
|
void sdUIEditW::OnReadOnlyChanged( const float oldValue, const float newValue ) {
|
|
MakeLayoutDirty();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnFlagsChanged
|
|
============
|
|
*/
|
|
void sdUIEditW::OnFlagsChanged( const float oldValue, const float newValue ) {
|
|
if ( FlagChanged( oldValue, newValue, WF_COLOR_ESCAPES ) ) {
|
|
MakeLayoutDirty();
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_IsWhitespace
|
|
============
|
|
*/
|
|
void sdUIEditW::Script_IsWhitespace( sdUIFunctionStack& stack ) {
|
|
for( int i = 0; i < editText.GetValue().Length(); i++ ) {
|
|
const wchar_t& c = editText.GetValue()[ i ];
|
|
if( idWStr::IsColor( &c ) ) {
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
if( c != L'\n' && c != L' ' ) {
|
|
stack.Push( false );
|
|
return;
|
|
}
|
|
}
|
|
stack.Push( true );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnInputInit
|
|
============
|
|
*/
|
|
void sdUIEditW::OnLanguageInit() {
|
|
if ( GetUI()->IsFocused( this ) ) {
|
|
if ( sys->IME().LangSupportsIME() ) {
|
|
sys->IME().Enable( true );
|
|
}
|
|
}
|
|
|
|
sdUIWindow::OnLanguageInit();
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnInputShutdown
|
|
============
|
|
*/
|
|
void sdUIEditW::OnLanguageShutdown() {
|
|
if ( GetUI()->IsFocused( this ) ) {
|
|
if ( sys->IME().LangSupportsIME() ) {
|
|
sys->IME().FinalizeString();
|
|
sys->IME().Enable( false );
|
|
}
|
|
}
|
|
|
|
sdUIWindow::OnLanguageShutdown();
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnGainFocus
|
|
============
|
|
*/
|
|
void sdUIEditW::OnGainFocus( void ) {
|
|
sdUIWindow::OnGainFocus();
|
|
helper.OnGainFocus();
|
|
if ( sys->IME().LangSupportsIME() ) {
|
|
sys->IME().Enable( true );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::OnLoseFocus
|
|
============
|
|
*/
|
|
void sdUIEditW::OnLoseFocus( void ) {
|
|
sdUIWindow::OnLoseFocus();
|
|
if ( sys->IME().LangSupportsIME() ) {
|
|
sys->IME().FinalizeString();
|
|
sys->IME().Enable( false );
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::DrawIndicator
|
|
============
|
|
*/
|
|
void sdUIEditW::DrawIndicator() {
|
|
// If IME system is off, draw English indicator
|
|
const wchar_t* indicator = sys->IME().GetState() == sdIME::IME_STATE_ON ? sys->IME().GetIndicator() : L"A";
|
|
|
|
ActivateFont();
|
|
|
|
int fontHeight = deviceContext->GetFontHeight( cachedFontHandle, fontSize );
|
|
|
|
#if 1
|
|
int heightRequired;
|
|
|
|
if ( sys->IME().VerticalCandidateLine() ) {
|
|
heightRequired = ( fontHeight * sdIME::MAX_CANDLIST ) + 2;
|
|
} else {
|
|
heightRequired = fontHeight + 2;
|
|
}
|
|
|
|
sdBounds2D rect( cachedClientRect.x,
|
|
cachedClientRect.y + cachedClientRect.w,
|
|
fontHeight + 2,
|
|
fontHeight + 2 );
|
|
|
|
sdUIWindow* desktop = GetUI()->GetDesktop();
|
|
if ( desktop != NULL ) {
|
|
if ( rect.GetMins().y + heightRequired > desktop->GetWorldRect().w ) {
|
|
float height = rect.GetHeight();
|
|
rect.GetMins().y = cachedClientRect.y - height;
|
|
rect.GetMaxs().y = rect.GetMins().y + height;
|
|
}
|
|
} else {
|
|
if ( rect.GetMins().y + heightRequired > SCREEN_HEIGHT ) {
|
|
float height = rect.GetHeight();
|
|
rect.GetMins().y = cachedClientRect.y - height;
|
|
rect.GetMaxs().y = rect.GetMins().y + height;
|
|
}
|
|
}
|
|
|
|
sdBounds2D textRect( rect.GetMins().x + 1,
|
|
rect.GetMins().y + 1,
|
|
fontHeight,
|
|
fontHeight );
|
|
#else
|
|
sdBounds2D textRect( cachedClientRect.x + cachedClientRect.z + 1,
|
|
cachedClientRect.y + cachedClientRect.w,
|
|
fontHeight,
|
|
fontHeight );
|
|
sdBounds2D rect( cachedClientRect.x + cachedClientRect.z,
|
|
cachedClientRect.y + cachedClientRect.w,
|
|
fontHeight + 2,
|
|
fontHeight + 2 );
|
|
#endif
|
|
|
|
deviceContext->DrawRect( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), IMEFillColor );
|
|
deviceContext->DrawBox( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), 1.0f, IMEBorderColor );
|
|
|
|
deviceContext->SetFontSize( fontSize );
|
|
|
|
deviceContext->SetColor( IMETextColor );
|
|
deviceContext->DrawText( indicator, textRect, DTF_CENTER | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING );
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
============
|
|
sdUIEditW::DrawComposition
|
|
============
|
|
*/
|
|
void sdUIEditW::DrawComposition() {
|
|
const wchar_t* compStr = sys->IME().GetCompositionString();
|
|
|
|
ActivateFont();
|
|
deviceContext->SetFontSize( fontSize );
|
|
|
|
int textWidth, textHeight;
|
|
sdBounds2D screenBounds( 0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
|
|
deviceContext->GetTextDimensions( compStr, screenBounds, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING, cachedFontHandle, fontSize, textWidth, textHeight );
|
|
|
|
// Draw the window and string
|
|
sdBounds2D rect( cachedClientRect.x,
|
|
cachedClientRect.y + cachedClientRect.w,
|
|
textWidth,
|
|
textHeight );//2 * cachedClientRect.w );
|
|
|
|
if ( false /*sys->IME().GetPrimaryLanguage() == sdIME::IME_LANG_KOREAN*/ ) {
|
|
|
|
} else {
|
|
deviceContext->SetColor( idVec4( 1.0f, 1.0f, 1.0f, 0.3f ) );
|
|
deviceContext->DrawRect( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), 0.0f, 0.0f, 1.0f, 1.0f, declHolder.FindMaterial( "_whiteVertexColor" ) );
|
|
}
|
|
|
|
deviceContext->SetColor( colorWhite );
|
|
deviceContext->DrawText( compStr, rect, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING );
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::DrawCandidateReadingWindow
|
|
============
|
|
*/
|
|
void sdUIEditW::DrawCandidateReadingWindow( bool reading ) {
|
|
int numEntries = reading ? 4 : sdIME::MAX_CANDLIST;
|
|
|
|
ActivateFont();
|
|
deviceContext->SetFontSize( fontSize );
|
|
|
|
int textWidth, textHeight;
|
|
sdBounds2D screenBounds( 0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT );
|
|
|
|
int widthRequired = 0;
|
|
int lineHeight = 0;
|
|
int heightRequired = 0;
|
|
|
|
wchar_t candidateString[ sdIME::MAX_CANDIDATE_LENGTH + 4 ];
|
|
candidateString[ 0 ] = L'\0';
|
|
int firstSelected = 0;
|
|
int horizontalSelectedLen = 0;
|
|
|
|
int fontHeight = deviceContext->GetFontHeight( cachedFontHandle, fontSize );
|
|
|
|
if ( ( sys->IME().VerticalCandidateLine() && !reading ) ||
|
|
( !sys->IME().IsHorizontalReading() && reading ) ) {
|
|
// vertical window
|
|
for ( int i = 0; i < numEntries; i++ ) {
|
|
if ( *( sys->IME().GetCandidate( i ) ) == L'\0' ) {
|
|
numEntries = i;
|
|
break;
|
|
}
|
|
|
|
deviceContext->GetTextDimensions( sys->IME().GetCandidate( i ), screenBounds, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING, cachedFontHandle, fontSize, textWidth, textHeight );
|
|
|
|
widthRequired = Max( widthRequired, textWidth );
|
|
lineHeight = fontHeight;//Max( lineHeight, textHeight );
|
|
}
|
|
#if 0
|
|
heightRequired = lineHeight * numEntries;
|
|
#else
|
|
heightRequired = lineHeight * sdIME::MAX_CANDLIST;
|
|
#endif
|
|
} else {
|
|
// horizontal window
|
|
|
|
if ( reading ) {
|
|
//???
|
|
} else {
|
|
idWStr::Append( candidateString, sdIME::MAX_CANDIDATE_LENGTH + 2, L"\x00ab" );
|
|
|
|
for ( int i = 0; i < sdIME::MAX_CANDLIST; i++ ) {
|
|
if ( *( sys->IME().GetCandidate( i ) ) == L'\0' ) {
|
|
break;
|
|
}
|
|
|
|
wchar_t* entry = va( L"%ls", sys->IME().GetCandidate( i ) );
|
|
|
|
// If this is the selected entry, mark its character position
|
|
if ( sys->IME().GetCandidateSelection() == i ) {
|
|
firstSelected = idWStr::Length( candidateString );
|
|
horizontalSelectedLen = idWStr::Length( entry );
|
|
}
|
|
|
|
idWStr::Append( candidateString, sdIME::MAX_CANDIDATE_LENGTH + 4, entry );
|
|
}
|
|
|
|
idWStr::Append( candidateString, sdIME::MAX_CANDIDATE_LENGTH + 2, L"\x00bb" );
|
|
|
|
deviceContext->GetTextDimensions( candidateString, screenBounds, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING, cachedFontHandle, fontSize, textWidth, textHeight );
|
|
}
|
|
|
|
widthRequired = textWidth;
|
|
lineHeight = heightRequired = fontHeight;//textHeight;
|
|
}
|
|
|
|
// Draw the elements
|
|
|
|
#if 0
|
|
sdUIWindow* desktop = GetUI()->GetDesktop();
|
|
float textX, textY, rectX, rectY;
|
|
|
|
if ( desktop != NULL ) {
|
|
textX = ( desktop->GetWorldRect().z - ( widthRequired + 2 ) ) + 1;
|
|
textY = ( desktop->GetWorldRect().w - ( heightRequired + 2 ) ) + 1;
|
|
rectX = desktop->GetWorldRect().z - ( widthRequired + 2 );
|
|
rectY = desktop->GetWorldRect().w - ( heightRequired + 2 );
|
|
} else {
|
|
textX = ( SCREEN_WIDTH - ( widthRequired + 2 ) ) + 1;
|
|
textY = ( SCREEN_HEIGHT - ( heightRequired + 2 ) ) + 1;
|
|
rectX = SCREEN_WIDTH - ( widthRequired + 2 );
|
|
rectY = SCREEN_HEIGHT - ( heightRequired + 2 );
|
|
}
|
|
|
|
sdBounds2D textRect( textX,
|
|
textY,
|
|
widthRequired,
|
|
heightRequired );
|
|
sdBounds2D rect( rectX,
|
|
rectY,
|
|
widthRequired + 2,
|
|
heightRequired + 2 );
|
|
#else
|
|
sdBounds2D rect( cachedClientRect.x + fontHeight + 2,
|
|
cachedClientRect.y + cachedClientRect.w,
|
|
widthRequired + 2,
|
|
heightRequired + 2 );
|
|
|
|
sdUIWindow* desktop = GetUI()->GetDesktop();
|
|
if ( desktop != NULL ) {
|
|
if ( rect.GetMins().y + rect.GetHeight() > desktop->GetWorldRect().w ) {
|
|
float height = rect.GetHeight();
|
|
rect.GetMins().y = cachedClientRect.y - height;
|
|
rect.GetMaxs().y = rect.GetMins().y + height;
|
|
}
|
|
} else {
|
|
if ( rect.GetMins().y + rect.GetHeight() > SCREEN_HEIGHT ) {
|
|
float height = rect.GetHeight();
|
|
rect.GetMins().y = cachedClientRect.y - height;
|
|
rect.GetMaxs().y = rect.GetMins().y + height;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if ( ( sys->IME().VerticalCandidateLine() && !reading ) ||
|
|
( !sys->IME().IsHorizontalReading() && reading ) ) {
|
|
// Vertical candidate window
|
|
deviceContext->DrawRect( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), IMEFillColor );
|
|
deviceContext->DrawBox( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), 1.0f, IMEBorderColor );
|
|
|
|
for ( int i = 0; i < numEntries; i++ ) {
|
|
sdBounds2D textRect( rect.GetMins().x + 1,
|
|
rect.GetMins().y + i * lineHeight + 1,
|
|
widthRequired,
|
|
lineHeight );
|
|
|
|
if ( sys->IME().GetCandidateSelection() == i ) {
|
|
deviceContext->DrawRect( textRect.GetMins().x, textRect.GetMins().y, textRect.GetWidth(), textRect.GetHeight(), IMESelectionColor );
|
|
}
|
|
|
|
deviceContext->SetColor( IMETextColor );
|
|
deviceContext->DrawText( sys->IME().GetCandidate( i ), textRect, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING );
|
|
}
|
|
} else {
|
|
// Horizontal candidate window
|
|
sdBounds2D textRect( rect.GetMins().x + 1,
|
|
rect.GetMins().y + 1,
|
|
widthRequired,
|
|
heightRequired );
|
|
|
|
deviceContext->DrawRect( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), IMEFillColor );
|
|
deviceContext->DrawBox( rect.GetMins().x, rect.GetMins().y, rect.GetWidth(), rect.GetHeight(), 1.0f, IMEBorderColor );
|
|
|
|
if ( reading ) {
|
|
|
|
} else {
|
|
if ( horizontalSelectedLen > 0 ) {
|
|
// Draw selection
|
|
sdTextDimensionHelper tdh;
|
|
tdh.Init( candidateString, idWStr::Length( candidateString ), textRect, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING, cachedFontHandle, fontSize );
|
|
|
|
idVec2 drawBegin;
|
|
drawBegin.x = textRect.GetMins().x + tdh.GetWidth( 0, firstSelected - 1 );
|
|
drawBegin.y = textRect.GetMins().y;
|
|
|
|
idVec2 drawEnd;
|
|
drawEnd.x = drawBegin.x + tdh.GetWidth( firstSelected, firstSelected + horizontalSelectedLen - 1 );
|
|
drawEnd.y = textRect.GetMins().y;
|
|
|
|
deviceContext->DrawRect( drawBegin.x, drawBegin.y, drawEnd.x - drawBegin.x, textRect.GetHeight(), IMESelectionColor );
|
|
}
|
|
|
|
// Draw text
|
|
deviceContext->SetColor( IMETextColor );
|
|
deviceContext->DrawText( candidateString, textRect, DTF_LEFT | DTF_SINGLELINE | DTF_BOTTOM | DTF_NOCLIPPING );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_InsertText
|
|
============
|
|
*/
|
|
void sdUIEditW::Script_InsertText( sdUIFunctionStack& stack ) {
|
|
idWStr text;
|
|
stack.Pop( text );
|
|
helper.InsertText( text.c_str() );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_SurroundSelection
|
|
============
|
|
*/
|
|
void sdUIEditW::Script_SurroundSelection( sdUIFunctionStack& stack ) {
|
|
idWStr prefix;
|
|
stack.Pop( prefix );
|
|
|
|
idWStr suffix;
|
|
stack.Pop( suffix );
|
|
|
|
helper.SurroundSelection( prefix.c_str(), suffix.c_str() );
|
|
}
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_AnySelected
|
|
============
|
|
*/
|
|
void sdUIEditW::Script_AnySelected( sdUIFunctionStack& stack ) {
|
|
int selStart;
|
|
int selEnd;
|
|
helper.GetSelectionRange( selStart, selEnd );
|
|
stack.Push( selStart != selEnd );
|
|
}
|
|
|
|
|
|
/*
|
|
============
|
|
sdUIEditW::Script_SelectAll
|
|
============
|
|
*/
|
|
void sdUIEditW::Script_SelectAll( sdUIFunctionStack& stack ) {
|
|
helper.SelectAll();
|
|
}
|