在基于
GUI界面的软件交互时,最基本的输入就是编辑框了,比如下图里输入的用户名称和密码,在游戏界面的编辑框里输入文字是一个高技术难度的问题,因为Windows输入法调用,也是难点之一。
那么在第二人生里的用户名称和密码的编辑框是怎么样实现的呢?现在就来分析这部份的代码,它的类继承关系如下:
class LLLineEditor
: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor
LLLineEditor继续了
LLUICtrl类,说明它是一个控件类。它的主要显示代码如下:
#001 void LLLineEditor::draw()
#002 {
判断不能显示时就直接返回去。
#003
if( !getVisible() )
#004
{
#005
return;
#006
}
#007
获取显示字符串的长度。
#008
S32 text_len = mText.length();
#009
如果是密码的方式,就只显示为星字符串。
#010
LLString saved_text;
#011
if (mDrawAsterixes)
#012
{
#013
saved_text = mText.getString();
#014
LLString text;
#015
for (S32 i = 0; i
#016
{
#017
text += '*';
#018
}
#019
mText = text;
#020
}
#021
设置背景框的大小。
#022
// draw rectangle for the background
#023
LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );
根据边框的大小设置合适的显示背景。
#024
background.stretch( -mBorderThickness );
#025
#026
LLColor4 bg_color = mReadOnlyBgColor;
#027
显示背景的颜色。
#028
// drawing solids requires texturing be disabled
#029
{
#030
LLGLSNoTexture no_texture;
#031
// draw background for text
#032
if( !mReadOnly )
#033
{
#034
if( gFocusMgr.getKeyboardFocus() == this )
#035
{
#036
bg_color = mFocusBgColor;
#037
}
#038
else
#039
{
#040
bg_color = mWriteableBgColor;
#041
}
#042
}
#043
gl_rect_2d(background, bg_color);
#044
}
#045
#046
// draw text
#047
开始显示字符串。
#048
S32 cursor_bottom = background.mBottom + 1;
#049
S32 cursor_top = background.mTop - 1;
#050
获取字体显示的颜色。
#051
LLColor4 text_color;
#052
if (!mReadOnly)
#053
{
#054
if (!getTentative())
#055
{
#056
text_color = mFgColor;
#057
}
#058
else
#059
{
#060
text_color = mTentativeFgColor;
#061
}
#062
}
#063
else
#064
{
#065
text_color = mReadOnlyFgColor;
#066
}
#067
LLColor4 label_color = mTentativeFgColor;
#068
显示预先编辑的标志。
#069
if (hasPreeditString())
#070
{
#071
// Draw preedit markers. This needs to be before drawing letters.
#072
for (U32 i = 0; i
#073
{
#074
const S32 preedit_left = mPreeditPositions[i];
#075
const S32 preedit_right = mPreeditPositions[i + 1];
#076
if (preedit_right > mScrollHPos)
#077
{
#078
S32 preedit_pixels_left = findPixelNearestPos(llmax(preedit_left, mScrollHPos) - getCursor());
#079
S32 preedit_pixels_right = llmin(findPixelNearestPos(preedit_right - getCursor()), background.mRight);
#080
if (preedit_pixels_left >= background.mRight)
#081
{
#082
break;
#083
}
#084
if (mPreeditStandouts[i])
#085
{
#086
gl_rect_2d(preedit_pixels_left + PREEDIT_STANDOUT_GAP,
#087
background.mBottom + PREEDIT_STANDOUT_POSITION,
#088
preedit_pixels_right - PREEDIT_STANDOUT_GAP - 1,
#089
background.mBottom + PREEDIT_STANDOUT_POSITION -
#090 PREEDIT_STANDOUT_THICKNESS,
#091
(text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 -
#092 PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
#093
}
#094
else
#095
{
#096
gl_rect_2d(preedit_pixels_left + PREEDIT_MARKER_GAP,
#097
background.mBottom + PREEDIT_MARKER_POSITION,
#098
preedit_pixels_right - PREEDIT_MARKER_GAP - 1,
#099
background.mBottom + PREEDIT_MARKER_POSITION -
#100 PREEDIT_MARKER_THICKNESS,
#101
(text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 -
#102 PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
#103
}
#104
}
#105
}
#106
}
#107
#108
S32 rendered_text = 0;
#109
F32 rendered_pixels_right = (F32)mMinHPixels;
#110
F32 text_bottom = (F32)background.mBottom + (F32)UI_LINEEDITOR_V_PAD;
#111
显示选中的效果。
#112
if( (gFocusMgr.getKeyboardFocus() == this) && hasSelection() )
#113
{
#114
S32 select_left;
#115
S32 select_right;
#116
if( mSelectionStart
#117
{
#118
select_left = mSelectionStart;
#119
select_right = getCursor();
#120
}
#121
else
#122
{
#123
select_left = getCursor();
#124
select_right = mSelectionStart;
#125
}
#126
#127
if( select_left > mScrollHPos )
#128
{
#129
// unselected, left side
#130
rendered_text = mGLFont->render(
#131
mText, mScrollHPos,
#132
rendered_pixels_right, text_bottom,
#133
text_color,
#134
LLFontGL::LEFT, LLFontGL::BOTTOM,
#135
LLFontGL::NORMAL,
#136
select_left - mScrollHPos,
#137
mMaxHPixels - llround(rendered_pixels_right),
#138
&rendered_pixels_right);
#139
}
#140
#141
if( (rendered_pixels_right <(F32)mMaxHPixels) && (rendered_text
#142
{
#143
LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f);
#144
// selected middle
#145
S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
#146
width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
#147
gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
#148
显示相应选中的字符串。
#149
rendered_text += mGLFont->render(
#150
mText, mScrollHPos + rendered_text,
#151
rendered_pixels_right, text_bottom,
#152
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
#153
LLFontGL::LEFT, LLFontGL::BOTTOM,
#154
LLFontGL::NORMAL,
#155
select_right - mScrollHPos - rendered_text,
#156
mMaxHPixels - llround(rendered_pixels_right),
#157
&rendered_pixels_right);
#158
}
#159
下面开始显示没有选中的字符串。
#160
if( (rendered_pixels_right <(F32)mMaxHPixels) && (rendered_text
#161
{
#162
// unselected, right side
#163
mGLFont->render(
#164
mText, mScrollHPos + rendered_text,
#165
rendered_pixels_right, text_bottom,
#166
text_color,
#167
LLFontGL::LEFT, LLFontGL::BOTTOM,
#168
LLFontGL::NORMAL,
#169
S32_MAX,
#170
mMaxHPixels - llround(rendered_pixels_right),
#171
&rendered_pixels_right);
#172
}
#173
}
#174
else
#175
{
#176
mGLFont->render(
#177
mText, mScrollHPos,
#178
rendered_pixels_right, text_bottom,
#179
text_color,
#180
LLFontGL::LEFT, LLFontGL::BOTTOM,
#181
LLFontGL::NORMAL,
#182
S32_MAX,
#183
mMaxHPixels - llround(rendered_pixels_right),
#184
&rendered_pixels_right);
#185
}
#186
如果正在编辑过程中,设置
IME在合适的位置。
#187
// If we're editing...
#188
if( gFocusMgr.getKeyboardFocus() == this)
#189
{
#190
// (Flash the cursor every half second)
#191
if (gShowTextEditCursor && !mReadOnly)
#192
{
#193
F32 elapsed = mKeystrokeTimer.getElapsedTimeF32();
#194
if( (elapsed
#195
{
#196
S32 cursor_left = findPixelNearestPos();
#197
cursor_left -= UI_LINEEDITOR_CURSOR_THICKNESS / 2;
#198
S32 cursor_right = cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS;
#199
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
#200
{
#201
const LLWString space(utf8str_to_wstring(LLString(" ")));
#202
S32 wswidth = mGLFont->getWidth(space.c_str());
#203
S32 width = mGLFont->getWidth(mText.getWString().c_str(), getCursor(), 1) + 1;
#204
cursor_right = cursor_left + llmax(wswidth, width);
#205
}
#206
// Use same color as text for the Cursor
#207
gl_rect_2d(cursor_left, cursor_top,
#208
cursor_right, cursor_bottom, text_color);
#209
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
#210
{
#211
mGLFont->render(mText, getCursor(), (F32)(cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS / 2),
#212 text_bottom,
#213
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
#214
LLFontGL::LEFT, LLFontGL::BOTTOM,
#215
LLFontGL::NORMAL,
#216
1);
#217
}
#218
#219
// Make sure the IME is in the right place
#220
S32 pixels_after_scroll = findPixelNearestPos(); // RCalculcate for IME position
#221
LLRect screen_pos = getScreenRect();
#222
LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - UI_LINEEDITOR_V_PAD );
#223
#224
ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
#225
ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
#226
getWindow()->setLanguageTextInput( ime_pos );
#227
}
#228
}
#229
显示子窗口。
#230
// Draw children (border)
#231
//mBorder->setVisible(TRUE);
#232
mBorder->setKeyboardFocusHighlight( TRUE );
#233
LLView::draw();
#234
mBorder->setKeyboardFocusHighlight( FALSE );
#235
//mBorder->setVisible(FALSE);
#236
}
#237
else // does not have keyboard input
#238
{
没有字符串,就显示为一个标签。
#239
// draw label if no text provided
#240
if (0 == mText.length())
#241
{
#242
mGLFont->render(mLabel.getWString(), 0,
#243
LABEL_HPAD, (F32)text_bottom,
#244
label_color,
#245
LLFontGL::LEFT, LLFontGL::BOTTOM,
#246
LLFontGL::NORMAL,
#247
S32_MAX,
#248
mMaxHPixels - llround(rendered_pixels_right),
#249
&rendered_pixels_right, FALSE);
#250
}
#251
// Draw children (border)
#252
LLView::draw();
#253
}
#254
保存相应的密码字符串。
#255
if (mDrawAsterixes)
#256
{
#257
mText = saved_text;
#258
}
#259 }
上面的函数先设置背景的颜色,并且把背景显示,然后根据是否为密码,或者选择字符串来作合适的处理,最后显示相应的字符串,并且输入法窗口在合适的位置上。