diff options
author | Alexander Gavriliuk <alexandrgproductengine@lindenlab.com> | 2023-10-03 13:54:07 +0200 |
---|---|---|
committer | Alexander Gavriliuk <alexandrgproductengine@lindenlab.com> | 2023-10-03 14:23:38 +0200 |
commit | be655fef7f1f5717df73dedf84e84b73d246a0ec (patch) | |
tree | 525370d04f50287b913b458814909b730db8a883 | |
parent | c3adae2a5ff3912ffb741b84a5d098d078da062b (diff) |
:x
-rw-r--r-- | indra/llrender/llfontgl.cpp | 4 | ||||
-rw-r--r-- | indra/llrender/llfontgl.h | 4 | ||||
-rw-r--r-- | indra/llui/llemojihelper.cpp | 9 | ||||
-rw-r--r-- | indra/newview/llpanelemojicomplete.cpp | 181 | ||||
-rw-r--r-- | indra/newview/llpanelemojicomplete.h | 13 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_emoji_complete.xml | 18 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/widgets/emoji_complete.xml | 3 |
7 files changed, 165 insertions, 67 deletions
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 165d83992b..3e8185de77 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -423,7 +423,7 @@ S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, cons return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); } -S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const { return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } @@ -488,7 +488,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars) const return getWidthF32(wchars, 0, S32_MAX); } -F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars ) const +F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars) const { LLWString wtext = utf8str_to_wstring(utf8text); return getWidthF32(wtext.c_str(), begin_offset, max_chars); diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 4d4f564033..c56dd96e00 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -135,12 +135,12 @@ public: S32 getWidth(const std::string& utf8text) const; S32 getWidth(const llwchar* wchars) const; - S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars ) const; + S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars) const; S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars) const; F32 getWidthF32(const std::string& utf8text) const; F32 getWidthF32(const llwchar* wchars) const; - F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const; + F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars) const; F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, bool no_padding = false) const; // The following are called often, frequently with large buffers, so do not use a string interface diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 1d7744cb55..9411f7cac5 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -109,11 +109,12 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c } LLFloater* pHelperFloater = mHelperHandle.get(); - LLRect rct = pHelperFloater->getRect(); - rct.setLeftTopAndSize(floater_x - HELPER_FLOATER_OFFSET_X, floater_y - HELPER_FLOATER_OFFSET_Y + rct.getHeight(), rct.getWidth(), rct.getHeight()); - pHelperFloater->setRect(rct); + LLRect rect = pHelperFloater->getRect(); + S32 left = floater_x - HELPER_FLOATER_OFFSET_X; + S32 top = floater_y - HELPER_FLOATER_OFFSET_Y + rect.getHeight(); + rect.setLeftTopAndSize(left, top, rect.getWidth(), rect.getHeight()); + pHelperFloater->setRect(rect); pHelperFloater->openFloater(LLSD().with("hint", short_code)); - gFloaterView->adjustToFitScreen(pHelperFloater, FALSE); } void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p) diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index 8fc84c0387..732531691b 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -32,6 +32,7 @@ #include "lluictrlfactory.h" constexpr U32 MIN_MOUSE_MOVE_DELTA = 4; +constexpr U32 MIN_SHORT_CODE_WIDTH = 100; // ============================================================================ // LLPanelEmojiComplete @@ -42,6 +43,7 @@ static LLDefaultChildRegistry::Register<LLPanelEmojiComplete> r("emoji_complete" LLPanelEmojiComplete::Params::Params() : autosize("autosize") , noscroll("noscroll") + , vertical("vertical") , max_emoji("max_emoji") , padding("padding") , selected_image("selected_image") @@ -52,11 +54,13 @@ LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p : LLUICtrl(p) , mAutoSize(p.autosize) , mNoScroll(p.noscroll) + , mVertical(p.vertical) , mMaxVisible(p.max_emoji) , mPadding(p.padding) , mSelectedImage(p.selected_image) + , mIconFont(LLFontGL::getFontEmojiHuge()) + , mTextFont(LLFontGL::getFontSansSerifBig()) { - setFont(p.font); } LLPanelEmojiComplete::~LLPanelEmojiComplete() @@ -65,29 +69,61 @@ LLPanelEmojiComplete::~LLPanelEmojiComplete() void LLPanelEmojiComplete::draw() { - if (!mEmojis.empty()) - { - const S32 centerY = mRenderRect.getCenterY(); - const size_t firstVisibleIdx = mScrollPos, lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mEmojis.size()) - 1; - - if (mCurSelected >= firstVisibleIdx && mCurSelected <= lastVisibleIdx) - { - const S32 emoji_left = mRenderRect.mLeft + (mCurSelected - firstVisibleIdx) * mEmojiWidth; - const S32 emoji_height = mFont->getLineHeight() + mPadding; - mSelectedImage->draw(emoji_left, centerY - emoji_height / 2, mEmojiWidth, emoji_height); - } - - U32 left = mRenderRect.mLeft + mPadding; - for (U32 curIdx = firstVisibleIdx; curIdx <= lastVisibleIdx; curIdx++) - { - mFont->render( - mEmojis, curIdx, - left, centerY, - LLColor4::white, LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW_SOFT, - 1, S32_MAX, nullptr, false, true); - left += mEmojiWidth; - } - } + if (mEmojis.empty()) + return; + + const size_t firstVisibleIdx = mScrollPos; + const size_t lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mEmojis.size()) - 1; + + if (mCurSelected >= firstVisibleIdx && mCurSelected <= lastVisibleIdx) + { + S32 x, y, width, height; + if (mVertical) + { + x = mRenderRect.mLeft; + y = mRenderRect.mTop - (mCurSelected - firstVisibleIdx + 1) * mEmojiHeight; + width = mRenderRect.getWidth(); + height = mEmojiHeight; + } + else + { + x = mRenderRect.mLeft + (mCurSelected - firstVisibleIdx) * mEmojiWidth; + y = mRenderRect.mBottom; + width = mEmojiWidth; + height = mRenderRect.getHeight(); + } + mSelectedImage->draw(x, y, width, height); + } + + S32 iconCenterX = mRenderRect.mLeft + mEmojiWidth / 2; + S32 iconCenterY = mRenderRect.mTop - mEmojiHeight / 2; + S32 textLeft = mVertical ? mRenderRect.mLeft + mEmojiWidth + mPadding : 0; + S32 textWidth = mVertical ? getRect().getWidth() - textLeft - mPadding : 0; + + for (U32 curIdx = firstVisibleIdx; curIdx <= lastVisibleIdx; curIdx++) + { + mIconFont->render(mEmojis, curIdx, iconCenterX, iconCenterY, + LLColor4::white, LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL, + LLFontGL::DROP_SHADOW_SOFT, 1, S32_MAX, nullptr, false, true); + if (mVertical) + { + llwchar emoji = mEmojis[curIdx]; + auto& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); + auto it = emoji2descr.find(emoji); + if (it != emoji2descr.end()) + { + const std::string& shortCode = it->second->ShortCodes.front(); + mTextFont->renderUTF8(shortCode, 0, textLeft, iconCenterY, LLColor4::white, + LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + shortCode.size(), textWidth, NULL, FALSE, FALSE); + } + iconCenterY -= mEmojiHeight; + } + else + { + iconCenterX += mEmojiWidth; + } + } } BOOL LLPanelEmojiComplete::handleHover(S32 x, S32 y, MASK mask) @@ -182,18 +218,49 @@ void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0; mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint); - size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; + size_t curEmojiIdx = curEmoji ? mEmojis.find(curEmoji) : std::string::npos; mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0; onEmojisChanged(); } +U32 LLPanelEmojiComplete::getMaxShortCodeWidth() const +{ + U32 max_width = 0; + auto& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); + for (llwchar emoji : mEmojis) + { + auto it = emoji2descr.find(emoji); + if (it != emoji2descr.end()) + { + const std::string& shortCode = it->second->ShortCodes.front(); + S32 width = mTextFont->getWidth(shortCode); + if (width > max_width) + { + max_width = width; + } + } + } + return max_width; +} + void LLPanelEmojiComplete::onEmojisChanged() { if (mAutoSize) { mVisibleEmojis = std::min(mEmojis.size(), mMaxVisible); - reshape(mVisibleEmojis * mEmojiWidth, getRect().getHeight(), false); + if (mVertical) + { + U32 maxShortCodeWidth = getMaxShortCodeWidth(); + U32 shortCodeWidth = std::max(maxShortCodeWidth, MIN_SHORT_CODE_WIDTH); + S32 width = mEmojiWidth + shortCodeWidth + mPadding * 2; + reshape(width, mVisibleEmojis * mEmojiHeight, false); + } + else + { + S32 height = getRect().getHeight(); + reshape(mVisibleEmojis * mEmojiWidth, height, false); + } } else { @@ -207,7 +274,8 @@ size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const { if (mRenderRect.pointInRect(x, y)) { - return mScrollPos + llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1); + U32 pos = mVertical ? (U32)(mRenderRect.mTop - y) / mEmojiHeight : x / mEmojiWidth; + return mScrollPos + llmin((size_t)pos, mEmojis.size() - 1); } return npos; } @@ -228,21 +296,32 @@ void LLPanelEmojiComplete::selectPrevious() select(mCurSelected - 1 >= 0 ? mCurSelected - 1 : mEmojis.size() - 1); } -void LLPanelEmojiComplete::setFont(const LLFontGL* fontp) -{ - mFont = fontp; - updateConstraints(); -} - void LLPanelEmojiComplete::updateConstraints() { - const S32 ctrlWidth = getLocalRect().getWidth(); - - mEmojiWidth = mFont->getWidthF32(u8"\U0001F431") + mPadding * 2; - mVisibleEmojis = ctrlWidth / mEmojiWidth; - mRenderRect = getLocalRect().stretch((ctrlWidth - mVisibleEmojis * mEmojiWidth) / -2, 0); - - updateScrollPos(); + mRenderRect = getLocalRect(); + S32 ctrlWidth = mRenderRect.getWidth(); + S32 ctrlHeight = mRenderRect.getHeight(); + + mEmojiHeight = mIconFont->getLineHeight() + mPadding * 2; + mEmojiWidth = mIconFont->getWidthF32(u8"\U0001F431") + mPadding * 2; + if (mVertical) + { + mVisibleEmojis = ctrlHeight / mEmojiHeight; + mRenderRect.mBottom = mRenderRect.mTop - mVisibleEmojis * mEmojiHeight; + } + else + { + mVisibleEmojis = ctrlWidth / mEmojiWidth; + S32 padding = (ctrlWidth - mVisibleEmojis * mEmojiWidth) / 2; + mRenderRect.mLeft += padding; + mRenderRect.mRight -= padding; + if (mEmojiHeight > ctrlHeight) + { + mEmojiHeight = ctrlHeight; + } + } + + updateScrollPos(); } void LLPanelEmojiComplete::updateScrollPos() @@ -302,11 +381,23 @@ BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_pare void LLFloaterEmojiComplete::onOpen(const LLSD& key) { - mEmojiCtrl->setEmojiHint(key["hint"].asString()); - if (0 == mEmojiCtrl->getEmojiCount()) - { - LLEmojiHelper::instance().hideHelper(); - } + mEmojiCtrl->setEmojiHint(key["hint"].asString()); + if (0 == mEmojiCtrl->getEmojiCount()) + { + LLEmojiHelper::instance().hideHelper(); + return; + } + + if (mEmojiCtrl->isAutoSize()) + { + LLRect outer_rect = getRect(); + const LLRect& inner_rect = mEmojiCtrl->getRect(); + outer_rect.mTop = outer_rect.mBottom + inner_rect.mBottom * 2 + inner_rect.getHeight(); + outer_rect.mRight = outer_rect.mLeft + inner_rect.mLeft * 2 + inner_rect.getWidth(); + setRect(outer_rect); + } + + gFloaterView->adjustToFitScreen(this, FALSE); } BOOL LLFloaterEmojiComplete::postBuild() diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index 02104efbcb..20d3413765 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -41,6 +41,7 @@ public: { Optional<bool> autosize; Optional<bool> noscroll; + Optional<bool> vertical; Optional<S32> max_emoji, padding; @@ -68,6 +69,8 @@ public: size_t getEmojiCount() const { return mEmojis.size(); } void setEmojis(const LLWString& emojis); void setEmojiHint(const std::string& hint); + bool isAutoSize() const { return mAutoSize; } + U32 getMaxShortCodeWidth() const; protected: void onEmojisChanged(); @@ -75,7 +78,6 @@ protected: void select(size_t emoji_idx); void selectNext(); void selectPrevious(); - void setFont(const LLFontGL* fontp); void updateConstraints(); void updateScrollPos(); @@ -84,14 +86,17 @@ protected: const bool mAutoSize = false; const bool mNoScroll = false; - const LLFontGL* mFont; - U16 mEmojiWidth = 0; + const bool mVertical = false; const size_t mMaxVisible = 0; const S32 mPadding = 8; - LLRect mRenderRect; const LLUIImagePtr mSelectedImage; + const LLFontGL* mIconFont; + const LLFontGL* mTextFont; LLWString mEmojis; + LLRect mRenderRect; + U16 mEmojiWidth = 0; + U16 mEmojiHeight = 0; size_t mVisibleEmojis = 0; size_t mFirstVisible = 0; size_t mScrollPos = 0; diff --git a/indra/newview/skins/default/xui/en/floater_emoji_complete.xml b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml index e9ea8f4de7..207a8af118 100644 --- a/indra/newview/skins/default/xui/en/floater_emoji_complete.xml +++ b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml @@ -1,5 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + name="emoji_complete" + single_instance="true" + layout="topleft" can_close="false" can_dock="false" can_drag_on_left="false" @@ -7,22 +10,21 @@ can_resize="false" can_tear_off="false" header_height="0" - layout="topleft" legacy_header_height="0" - height="40" - single_instance="true" width="240" + height="40" > <emoji_complete - autosize="true" - height="30" + name="emoji_complete_ctrl" follows="top|left" layout="topleft" - left="5" + autosize="true" + vertical="true" max_emoji="7" - name="emoji_complete_ctrl" - top="5" width="230" + height="30" + left="5" + top="5" > </emoji_complete> </floater> diff --git a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml index 370f1d174e..f9db441815 100644 --- a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml +++ b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml @@ -1,10 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <emoji_complete autosize="false" - font="EmojiHuge" hover_image="ListItem_Over" + selected_image="ListItem_Select" max_emoji="7" padding="8" - selected_image="ListItem_Select" > </emoji_complete> |