前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >第二人生的源码分析(九十二)LLLineEditor实现编辑框

第二人生的源码分析(九十二)LLLineEditor实现编辑框

作者头像
用户7886150
修改2021-02-14 15:32:05
修改2021-02-14 15:32:05
2930
举报
文章被收录于专栏:bit哲学院bit哲学院

参考链接: C++ llround()

在基于

 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 < mText.length(); 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 < mPreeditStandouts.size(); 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 < getCursor() )

 #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 < text_len) )

 #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 < text_len) )

 #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 < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) )

 #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 }

 上面的函数先设置背景的颜色,并且把背景显示,然后根据是否为密码,或者选择字符串来作合适的处理,最后显示相应的字符串,并且输入法窗口在合适的位置上。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档