Merge branch 'DRTVWR-489' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/llpanelemojicomplete.cpp # indra/newview/skins/default/xui/en/widgets/emoji_complete.xmlmeow-7.2.2
commit
478cbd595b
|
|
@ -449,7 +449,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);
|
||||
}
|
||||
|
|
@ -514,7 +514,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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
//
|
||||
|
||||
constexpr char DEFAULT_EMOJI_HELPER_FLOATER[] = "emoji_complete";
|
||||
constexpr S32 HELPER_FLOATER_OFFSET_X = 20;
|
||||
constexpr S32 HELPER_FLOATER_OFFSET_X = 0;
|
||||
constexpr S32 HELPER_FLOATER_OFFSET_Y = 0;
|
||||
|
||||
// ============================================================================
|
||||
|
|
@ -109,9 +109,11 @@ 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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1080,7 +1080,7 @@ S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
|
|||
// store text segments
|
||||
getSegmentsInRange(segments_to_remove, pos, pos + length, false);
|
||||
|
||||
if(pos <= end_pos)
|
||||
if (pos <= end_pos)
|
||||
{
|
||||
removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
|
||||
}
|
||||
|
|
@ -1104,11 +1104,12 @@ S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
|
|||
// a pseudo-tab (up to for spaces in a row)
|
||||
void LLTextEditor::removeCharOrTab()
|
||||
{
|
||||
if( !getEnabled() )
|
||||
if (!getEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( mCursorPos > 0 )
|
||||
|
||||
if (mCursorPos > 0)
|
||||
{
|
||||
S32 chars_to_remove = 1;
|
||||
|
||||
|
|
@ -1123,14 +1124,14 @@ void LLTextEditor::removeCharOrTab()
|
|||
if (offset > 0)
|
||||
{
|
||||
chars_to_remove = offset % SPACES_PER_TAB;
|
||||
if( chars_to_remove == 0 )
|
||||
if (chars_to_remove == 0)
|
||||
{
|
||||
chars_to_remove = SPACES_PER_TAB;
|
||||
}
|
||||
|
||||
for( S32 i = 0; i < chars_to_remove; i++ )
|
||||
for (S32 i = 0; i < chars_to_remove; i++)
|
||||
{
|
||||
if (text[ mCursorPos - i - 1] != ' ')
|
||||
if (text[mCursorPos - i - 1] != ' ')
|
||||
{
|
||||
// Fewer than a full tab's worth of spaces, so
|
||||
// just delete a single character.
|
||||
|
|
@ -1144,8 +1145,10 @@ void LLTextEditor::removeCharOrTab()
|
|||
for (S32 i = 0; i < chars_to_remove; i++)
|
||||
{
|
||||
setCursorPos(mCursorPos - 1);
|
||||
remove( mCursorPos, 1, FALSE );
|
||||
remove(mCursorPos, 1, false);
|
||||
}
|
||||
|
||||
tryToShowEmojiHelper();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1156,7 +1159,7 @@ void LLTextEditor::removeCharOrTab()
|
|||
// Remove a single character from the text
|
||||
S32 LLTextEditor::removeChar(S32 pos)
|
||||
{
|
||||
return remove( pos, 1, FALSE );
|
||||
return remove(pos, 1, false);
|
||||
}
|
||||
|
||||
void LLTextEditor::removeChar()
|
||||
|
|
@ -1165,10 +1168,12 @@ void LLTextEditor::removeChar()
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCursorPos > 0)
|
||||
{
|
||||
setCursorPos(mCursorPos - 1);
|
||||
removeChar(mCursorPos);
|
||||
tryToShowEmojiHelper();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1256,17 +1261,7 @@ void LLTextEditor::addChar(llwchar wc)
|
|||
}
|
||||
|
||||
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
|
||||
|
||||
if (!mReadOnly && mShowEmojiHelper)
|
||||
{
|
||||
LLWString wtext(getWText()); S32 shortCodePos;
|
||||
if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos))
|
||||
{
|
||||
const LLRect cursorRect = getLocalRectFromDocIndex(mCursorPos - 1);
|
||||
const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos - shortCodePos);
|
||||
LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode), std::bind(&LLTextEditor::handleEmojiCommit, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
tryToShowEmojiHelper();
|
||||
|
||||
if (!mReadOnly && mAutoreplaceCallback != NULL)
|
||||
{
|
||||
|
|
@ -1286,6 +1281,23 @@ void LLTextEditor::addChar(llwchar wc)
|
|||
}
|
||||
}
|
||||
|
||||
void LLTextEditor::tryToShowEmojiHelper()
|
||||
{
|
||||
if (mReadOnly || !mShowEmojiHelper)
|
||||
return;
|
||||
|
||||
S32 shortCodePos;
|
||||
LLWString wtext(getWText());
|
||||
if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos))
|
||||
{
|
||||
const LLRect cursorRect(getLocalRectFromDocIndex(shortCodePos));
|
||||
const LLWString wpart(wtext.substr(shortCodePos, mCursorPos - shortCodePos));
|
||||
const std::string part(wstring_to_utf8str(wpart));
|
||||
auto cb = [this](llwchar emoji) { handleEmojiCommit(emoji); };
|
||||
LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, part, cb);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTextEditor::addLineBreakChar(BOOL group_together)
|
||||
{
|
||||
if( !getEnabled() )
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ protected:
|
|||
S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
|
||||
S32 remove(S32 pos, S32 length, bool group_with_next_op);
|
||||
|
||||
void tryToShowEmojiHelper();
|
||||
void focusLostHelper();
|
||||
void updateAllowingLanguageInput();
|
||||
BOOL hasPreeditString() const;
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ BOOL LLView::focusNext(LLView::child_list_t & result)
|
|||
{
|
||||
next = result.rbegin();
|
||||
}
|
||||
if((*next)->isCtrl())
|
||||
if ((*next)->isCtrl() && ((LLUICtrl*)*next)->hasTabStop())
|
||||
{
|
||||
LLUICtrl * ctrl = static_cast<LLUICtrl*>(*next);
|
||||
ctrl->setFocus(TRUE);
|
||||
|
|
|
|||
|
|
@ -2473,13 +2473,20 @@ bool FSFloaterIM::applyRectControl()
|
|||
|
||||
void FSFloaterIM::onEmojiRecentPanelToggleBtnClicked(FSFloaterIM* self)
|
||||
{
|
||||
bool restore_focus = (gFocusMgr.getLastKeyboardFocus() == self->mInputEditor);
|
||||
|
||||
BOOL show = !self->mEmojiRecentPanel->getVisible();
|
||||
if (show)
|
||||
{
|
||||
self->initEmojiRecentPanel(true);
|
||||
self->initEmojiRecentPanel(!restore_focus);
|
||||
}
|
||||
self->mEmojiRecentPanel->setVisible(show);
|
||||
self->mEmojiRecentPanelToggleBtn->setImageOverlay(show ? "Arrow_Up" : "Arrow_Down");
|
||||
|
||||
if (restore_focus)
|
||||
{
|
||||
self->mInputEditor->setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterIM::initEmojiRecentPanel(bool moveFocus)
|
||||
|
|
|
|||
|
|
@ -971,13 +971,20 @@ void FSFloaterNearbyChat::handleMinimized(bool minimized)
|
|||
|
||||
void FSFloaterNearbyChat::onEmojiRecentPanelToggleBtnClicked(FSFloaterNearbyChat* self)
|
||||
{
|
||||
bool restore_focus = (gFocusMgr.getLastKeyboardFocus() == self->mInputEditor);
|
||||
|
||||
BOOL show = !self->mEmojiRecentPanel->getVisible();
|
||||
if (show)
|
||||
{
|
||||
self->initEmojiRecentPanel(true);
|
||||
self->initEmojiRecentPanel(!restore_focus);
|
||||
}
|
||||
self->mEmojiRecentPanel->setVisible(show);
|
||||
self->mEmojiRecentPanelToggleBtn->setImageOverlay(show ? "Arrow_Up" : "Arrow_Down");
|
||||
|
||||
if (restore_focus)
|
||||
{
|
||||
self->mInputEditor->setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterNearbyChat::initEmojiRecentPanel(bool moveFocus)
|
||||
|
|
|
|||
|
|
@ -293,6 +293,9 @@ void LLFloaterIMContainer::onOpen(const LLSD& key)
|
|||
LLMultiFloater::onOpen(key);
|
||||
reSelectConversation();
|
||||
assignResizeLimits();
|
||||
|
||||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession);
|
||||
session_floater->onOpen(key);
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
|
|||
|
|
@ -455,12 +455,19 @@ void LLFloaterIMSessionTab::onInputEditorClicked()
|
|||
|
||||
void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self)
|
||||
{
|
||||
bool restore_focus = (gFocusMgr.getLastKeyboardFocus() == self->mInputEditor);
|
||||
|
||||
BOOL show = !self->mEmojiRecentPanel->getVisible();
|
||||
if (show)
|
||||
{
|
||||
self->initEmojiRecentPanel(true);
|
||||
self->initEmojiRecentPanel(!restore_focus);
|
||||
}
|
||||
self->mEmojiRecentPanel->setVisible(show);
|
||||
|
||||
if (restore_focus)
|
||||
{
|
||||
self->mInputEditor->setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPickerToggleBtnClicked(LLFloaterIMSessionTab* self)
|
||||
|
|
@ -1122,6 +1129,8 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
|
|||
}
|
||||
|
||||
mInputButtonPanel->setVisible(isTornOff());
|
||||
|
||||
setFocus(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (mEmojis.empty())
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
const size_t firstVisibleIdx = mScrollPos;
|
||||
const size_t lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mEmojis.size()) - 1;
|
||||
|
||||
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 (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 = (U16)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();
|
||||
mRenderRect = getLocalRect();
|
||||
S32 ctrlWidth = mRenderRect.getWidth();
|
||||
S32 ctrlHeight = mRenderRect.getHeight();
|
||||
|
||||
mEmojiWidth = mFont->getWidthF32(u8"\U0001F431") + mPadding * 2;
|
||||
mVisibleEmojis = ctrlWidth / mEmojiWidth;
|
||||
mRenderRect = getLocalRect().stretch((ctrlWidth - mVisibleEmojis * mEmojiWidth) / -2, 0);
|
||||
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();
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
background_visible="true"
|
||||
background_opaque="true"
|
||||
bg_opaque_color="FrogGreen"
|
||||
tab_stop="false"
|
||||
bottom="0"
|
||||
height="2"
|
||||
width="20"
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@
|
|||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
height="35"
|
||||
height="30"
|
||||
auto_resize="false"
|
||||
name="chat_layout_panel">
|
||||
<layout_stack
|
||||
|
|
@ -249,7 +249,7 @@
|
|||
name="input_panels"
|
||||
top="0"
|
||||
bottom="-1"
|
||||
left="0"
|
||||
left="1"
|
||||
right="-1">
|
||||
<layout_panel
|
||||
name="input_editor_layout_panel">
|
||||
|
|
@ -260,7 +260,7 @@
|
|||
default_icon_name="Generic_Person"
|
||||
layout="topleft"
|
||||
left="3"
|
||||
bottom="-9"
|
||||
bottom="-4"
|
||||
visible="false"
|
||||
width="20" />
|
||||
<group_icon
|
||||
|
|
@ -270,7 +270,7 @@
|
|||
default_icon_name="Generic_Group"
|
||||
layout="topleft"
|
||||
left="3"
|
||||
bottom="-9"
|
||||
bottom="-4"
|
||||
visible="false"
|
||||
width="20" />
|
||||
<icon
|
||||
|
|
@ -279,7 +279,7 @@
|
|||
image_name="Nearby_chat_icon"
|
||||
layout="topleft"
|
||||
left="3"
|
||||
bottom="-9"
|
||||
bottom="-4"
|
||||
name="nearby_chat_icon"
|
||||
visible="false"
|
||||
width="20"/>
|
||||
|
|
@ -296,7 +296,7 @@
|
|||
max_length="1023"
|
||||
spellcheck="true"
|
||||
tab_group="3"
|
||||
bottom="-8"
|
||||
bottom="-3"
|
||||
left_pad="5"
|
||||
right="-30"
|
||||
wrap="true" />
|
||||
|
|
@ -309,7 +309,7 @@
|
|||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
bottom="-7"
|
||||
bottom="-2"
|
||||
right="-1"
|
||||
height="25"
|
||||
width="25"/>
|
||||
|
|
@ -335,7 +335,7 @@
|
|||
</layout_panel>
|
||||
<layout_panel
|
||||
name="emoji_recent_layout_panel"
|
||||
height="35"
|
||||
height="30"
|
||||
auto_resize="false">
|
||||
<text
|
||||
name="emoji_recent_empty_text"
|
||||
|
|
@ -345,8 +345,8 @@
|
|||
h_pad="20"
|
||||
v_pad="10"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-60"
|
||||
left="1"
|
||||
right="-65"
|
||||
height="30"
|
||||
>Recently used emojis will appear here</text>
|
||||
<emoji_complete
|
||||
|
|
@ -355,8 +355,8 @@
|
|||
layout="topleft"
|
||||
max_emoji="20"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-60"
|
||||
left="1"
|
||||
right="-65"
|
||||
height="30"/>
|
||||
<button
|
||||
name="emoji_picker_toggle_btn"
|
||||
|
|
@ -365,8 +365,8 @@
|
|||
follows="right|bottom"
|
||||
layout="topleft"
|
||||
bottom="-5"
|
||||
right="-5"
|
||||
height="30"
|
||||
right="-3"
|
||||
height="20"
|
||||
width="60"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<emoji_complete
|
||||
autosize="false"
|
||||
font="EmojiHuge"
|
||||
selected_image="ListItem_Select"
|
||||
max_emoji="7"
|
||||
padding="8"
|
||||
selected_image="ListItem_Select"
|
||||
>
|
||||
</emoji_complete>
|
||||
|
|
|
|||
Loading…
Reference in New Issue