SL-20402 Emoji Completion floater - use vertical scrollbar when needed
parent
66aee79e3e
commit
9f8763cae1
|
|
@ -475,13 +475,15 @@ void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent)
|
|||
{
|
||||
up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, mThickness));
|
||||
down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, mThickness));
|
||||
up_button->setOrigin(up_button->getRect().mLeft, getRect().getHeight() - up_button->getRect().getHeight());
|
||||
up_button->setOrigin(0, getRect().getHeight() - up_button->getRect().getHeight());
|
||||
down_button->setOrigin(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
up_button->reshape(llmin(getRect().getWidth() / 2, mThickness), up_button->getRect().getHeight());
|
||||
down_button->reshape(llmin(getRect().getWidth() / 2, mThickness), down_button->getRect().getHeight());
|
||||
down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(), down_button->getRect().mBottom);
|
||||
up_button->setOrigin(0, 0);
|
||||
down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(), 0);
|
||||
}
|
||||
updateThumbRect();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@
|
|||
#include "llemojidictionary.h"
|
||||
#include "llemojihelper.h"
|
||||
#include "llpanelemojicomplete.h"
|
||||
#include "llscrollbar.h"
|
||||
#include "lluictrlfactory.h"
|
||||
|
||||
constexpr U32 MIN_MOUSE_MOVE_DELTA = 4;
|
||||
constexpr U32 MIN_SHORT_CODE_WIDTH = 100;
|
||||
constexpr U32 DEF_PADDING = 8;
|
||||
|
||||
// ============================================================================
|
||||
// LLPanelEmojiComplete
|
||||
|
|
@ -41,26 +43,35 @@ constexpr U32 MIN_SHORT_CODE_WIDTH = 100;
|
|||
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")
|
||||
: autosize("autosize")
|
||||
, noscroll("noscroll")
|
||||
, vertical("vertical")
|
||||
, max_visible("max_visible")
|
||||
, padding("padding", DEF_PADDING)
|
||||
, selected_image("selected_image")
|
||||
{
|
||||
}
|
||||
|
||||
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())
|
||||
: LLUICtrl(p)
|
||||
, mAutoSize(p.autosize)
|
||||
, mNoScroll(p.noscroll)
|
||||
, mVertical(p.vertical)
|
||||
, mMaxVisible(p.max_visible)
|
||||
, mPadding(p.padding)
|
||||
, mSelectedImage(p.selected_image)
|
||||
, mIconFont(LLFontGL::getFontEmojiHuge())
|
||||
, mTextFont(LLFontGL::getFontSansSerifBig())
|
||||
, mScrollbar(nullptr)
|
||||
{
|
||||
if (mVertical)
|
||||
{
|
||||
LLScrollbar::Params sbparams;
|
||||
sbparams.orientation(LLScrollbar::VERTICAL);
|
||||
sbparams.change_callback([this](S32 index, LLScrollbar*) { onScrollbarChange(index); });
|
||||
mScrollbar = LLUICtrlFactory::create<LLScrollbar>(sbparams);
|
||||
addChild(mScrollbar);
|
||||
}
|
||||
}
|
||||
|
||||
LLPanelEmojiComplete::~LLPanelEmojiComplete()
|
||||
|
|
@ -69,13 +80,15 @@ LLPanelEmojiComplete::~LLPanelEmojiComplete()
|
|||
|
||||
void LLPanelEmojiComplete::draw()
|
||||
{
|
||||
LLUICtrl::draw();
|
||||
|
||||
if (mEmojis.empty())
|
||||
return;
|
||||
|
||||
const size_t firstVisibleIdx = mScrollPos;
|
||||
const size_t lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mEmojis.size()) - 1;
|
||||
const size_t lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mTotalEmojis);
|
||||
|
||||
if (mCurSelected >= firstVisibleIdx && mCurSelected <= lastVisibleIdx)
|
||||
if (mCurSelected >= firstVisibleIdx && mCurSelected < lastVisibleIdx)
|
||||
{
|
||||
S32 x, y, width, height;
|
||||
if (mVertical)
|
||||
|
|
@ -100,7 +113,7 @@ void LLPanelEmojiComplete::draw()
|
|||
S32 textLeft = mVertical ? mRenderRect.mLeft + mEmojiWidth + mPadding : 0;
|
||||
S32 textWidth = mVertical ? getRect().getWidth() - textLeft - mPadding : 0;
|
||||
|
||||
for (U32 curIdx = firstVisibleIdx; curIdx <= lastVisibleIdx; curIdx++)
|
||||
for (U32 curIdx = firstVisibleIdx; curIdx < lastVisibleIdx; curIdx++)
|
||||
{
|
||||
mIconFont->render(mEmojis, curIdx, iconCenterX, iconCenterY,
|
||||
LLColor4::white, LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL,
|
||||
|
|
@ -128,100 +141,154 @@ void LLPanelEmojiComplete::draw()
|
|||
|
||||
BOOL LLPanelEmojiComplete::handleHover(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
LLVector2 curHover(x, y);
|
||||
if ((mLastHover - curHover).lengthSquared() > MIN_MOUSE_MOVE_DELTA)
|
||||
{
|
||||
mCurSelected = posToIndex(x, y);
|
||||
mLastHover = curHover;
|
||||
}
|
||||
if (mScrollbar && mScrollbar->getVisible() && childrenHandleHover(x, y, mask))
|
||||
return TRUE;
|
||||
|
||||
return TRUE;
|
||||
LLVector2 curHover(x, y);
|
||||
if ((mLastHover - curHover).lengthSquared() > MIN_MOUSE_MOVE_DELTA)
|
||||
{
|
||||
size_t index = posToIndex(x, y);
|
||||
if (index < mTotalEmojis)
|
||||
mCurSelected = index;
|
||||
mLastHover = curHover;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent)
|
||||
{
|
||||
bool handled = false;
|
||||
if (MASK_NONE == mask)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KEY_LEFT:
|
||||
case KEY_UP:
|
||||
selectPrevious();
|
||||
handled = true;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
case KEY_DOWN:
|
||||
selectNext();
|
||||
handled = true;
|
||||
break;
|
||||
case KEY_RETURN:
|
||||
if (!mEmojis.empty())
|
||||
{
|
||||
onCommit();
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool handled = false;
|
||||
if (mTotalEmojis && MASK_NONE == mask)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KEY_HOME:
|
||||
select(0);
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
if (handled)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return LLUICtrl::handleKey(key, mask, called_from_parent);
|
||||
case KEY_END:
|
||||
select(mTotalEmojis - 1);
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case KEY_PAGE_DOWN:
|
||||
select(mCurSelected + mVisibleEmojis - 1);
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case KEY_PAGE_UP:
|
||||
select(mCurSelected - llmin(mCurSelected, mVisibleEmojis + 1));
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case KEY_LEFT:
|
||||
case KEY_UP:
|
||||
selectPrevious();
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case KEY_RIGHT:
|
||||
case KEY_DOWN:
|
||||
selectNext();
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case KEY_RETURN:
|
||||
onCommit();
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (handled)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return LLUICtrl::handleKey(key, mask, called_from_parent);
|
||||
}
|
||||
|
||||
BOOL LLPanelEmojiComplete::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
mCurSelected = posToIndex(x, y);
|
||||
mLastHover = LLVector2(x, y);
|
||||
if (mScrollbar && mScrollbar->getVisible() && childrenHandleMouseDown(x, y, mask))
|
||||
return TRUE;
|
||||
|
||||
return TRUE;
|
||||
mCurSelected = posToIndex(x, y);
|
||||
mLastHover = LLVector2(x, y);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLPanelEmojiComplete::handleMouseUp(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
mCurSelected = posToIndex(x, y);
|
||||
onCommit();
|
||||
if (mScrollbar && mScrollbar->getVisible() && childrenHandleMouseUp(x, y, mask))
|
||||
return TRUE;
|
||||
|
||||
return TRUE;
|
||||
mCurSelected = posToIndex(x, y);
|
||||
onCommit();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLPanelEmojiComplete::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
||||
{
|
||||
if (mNoScroll)
|
||||
return FALSE;
|
||||
|
||||
if (mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel(x, y, clicks))
|
||||
{
|
||||
mCurSelected = posToIndex(x, y);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (mTotalEmojis > mVisibleEmojis)
|
||||
{
|
||||
mScrollPos = llclamp<size_t>(mScrollPos + clicks, 0, mTotalEmojis - mVisibleEmojis);
|
||||
mCurSelected = posToIndex(x, y);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::onCommit()
|
||||
{
|
||||
if (mCurSelected < mEmojis.size())
|
||||
{
|
||||
LLWString wstr;
|
||||
wstr.push_back(mEmojis.at(mCurSelected));
|
||||
setValue(wstring_to_utf8str(wstr));
|
||||
LLUICtrl::onCommit();
|
||||
}
|
||||
if (mCurSelected < mTotalEmojis)
|
||||
{
|
||||
LLWString wstr;
|
||||
wstr.push_back(mEmojis.at(mCurSelected));
|
||||
setValue(wstring_to_utf8str(wstr));
|
||||
LLUICtrl::onCommit();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
LLUICtrl::reshape(width, height, called_from_parent);
|
||||
updateConstraints();
|
||||
LLUICtrl::reshape(width, height, called_from_parent);
|
||||
updateConstraints();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::setEmojis(const LLWString& emojis)
|
||||
{
|
||||
mEmojis = emojis;
|
||||
mCurSelected = 0;
|
||||
mEmojis = emojis;
|
||||
mTotalEmojis = mEmojis.size();
|
||||
mCurSelected = 0;
|
||||
|
||||
onEmojisChanged();
|
||||
onEmojisChanged();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::setEmojiHint(const std::string& hint)
|
||||
{
|
||||
llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0;
|
||||
llwchar curEmoji = mCurSelected < mTotalEmojis ? mEmojis.at(mCurSelected) : 0;
|
||||
|
||||
mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint);
|
||||
size_t curEmojiIdx = curEmoji ? mEmojis.find(curEmoji) : std::string::npos;
|
||||
mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0;
|
||||
mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint);
|
||||
mTotalEmojis = mEmojis.size();
|
||||
size_t curEmojiIdx = curEmoji ? mEmojis.find(curEmoji) : std::string::npos;
|
||||
mCurSelected = std::string::npos != curEmojiIdx ? curEmojiIdx : 0;
|
||||
|
||||
onEmojisChanged();
|
||||
onEmojisChanged();
|
||||
}
|
||||
|
||||
U32 LLPanelEmojiComplete::getMaxShortCodeWidth() const
|
||||
|
|
@ -246,79 +313,104 @@ U32 LLPanelEmojiComplete::getMaxShortCodeWidth() const
|
|||
|
||||
void LLPanelEmojiComplete::onEmojisChanged()
|
||||
{
|
||||
if (mAutoSize)
|
||||
{
|
||||
mVisibleEmojis = std::min(mEmojis.size(), mMaxVisible);
|
||||
if (mAutoSize)
|
||||
{
|
||||
S32 width, height;
|
||||
mVisibleEmojis = llmin(mTotalEmojis, mMaxVisible);
|
||||
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);
|
||||
U32 shortCodeWidth = llmax(maxShortCodeWidth, MIN_SHORT_CODE_WIDTH);
|
||||
width = mEmojiWidth + shortCodeWidth + mPadding * 2;
|
||||
if (!mNoScroll && mVisibleEmojis < mTotalEmojis)
|
||||
{
|
||||
width += mScrollbar->getThickness();
|
||||
}
|
||||
height = mVisibleEmojis * mEmojiHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 height = getRect().getHeight();
|
||||
reshape(mVisibleEmojis * mEmojiWidth, height, false);
|
||||
width = mVisibleEmojis * mEmojiWidth;
|
||||
height = getRect().getHeight();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
updateConstraints();
|
||||
}
|
||||
LLUICtrl::reshape(width, height, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
mVisibleEmojis = mVertical ? getRect().getHeight() / mEmojiHeight : getRect().getWidth() / mEmojiWidth;
|
||||
}
|
||||
|
||||
mScrollPos = llmin(mScrollPos, mEmojis.size());
|
||||
updateConstraints();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::onScrollbarChange(S32 index)
|
||||
{
|
||||
mScrollPos = llclamp<size_t>(index, 0, mTotalEmojis - mVisibleEmojis);
|
||||
}
|
||||
|
||||
size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const
|
||||
{
|
||||
if (mRenderRect.pointInRect(x, y))
|
||||
{
|
||||
U32 pos = mVertical ? (U32)(mRenderRect.mTop - y) / mEmojiHeight : x / mEmojiWidth;
|
||||
return mScrollPos + llmin((size_t)pos, mEmojis.size() - 1);
|
||||
}
|
||||
return npos;
|
||||
if (mRenderRect.pointInRect(x, y))
|
||||
{
|
||||
U32 pos = mVertical ? (U32)(mRenderRect.mTop - y) / mEmojiHeight : x / mEmojiWidth;
|
||||
return llmin(mScrollPos + pos, mTotalEmojis - 1);
|
||||
}
|
||||
return std::string::npos;
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::select(size_t emoji_idx)
|
||||
{
|
||||
mCurSelected = llclamp<size_t>(emoji_idx, 0, mEmojis.size());
|
||||
updateScrollPos();
|
||||
mCurSelected = llclamp<size_t>(emoji_idx, 0, mTotalEmojis - 1);
|
||||
|
||||
updateScrollPos();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::selectNext()
|
||||
{
|
||||
select(mCurSelected + 1 < mEmojis.size() ? mCurSelected + 1 : 0);
|
||||
if (!mTotalEmojis)
|
||||
return;
|
||||
|
||||
mCurSelected = (mCurSelected < mTotalEmojis - 1) ? mCurSelected + 1 : 0;
|
||||
|
||||
updateScrollPos();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::selectPrevious()
|
||||
{
|
||||
select(mCurSelected - 1 >= 0 ? mCurSelected - 1 : mEmojis.size() - 1);
|
||||
if (!mTotalEmojis)
|
||||
return;
|
||||
|
||||
mCurSelected = (mCurSelected && mCurSelected < mTotalEmojis) ? mCurSelected - 1 : mTotalEmojis - 1;
|
||||
|
||||
updateScrollPos();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::updateConstraints()
|
||||
{
|
||||
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;
|
||||
mEmojiHeight = mIconFont->getLineHeight() + mPadding * 2;
|
||||
if (!mNoScroll && mVisibleEmojis < mTotalEmojis)
|
||||
{
|
||||
mRenderRect.mRight -= mScrollbar->getThickness();
|
||||
mScrollbar->setDocSize(mTotalEmojis);
|
||||
mScrollbar->setPageSize(mVisibleEmojis);
|
||||
mScrollbar->setOrigin(mRenderRect.mRight, 0);
|
||||
mScrollbar->reshape(mScrollbar->getThickness(), mRenderRect.mTop, TRUE);
|
||||
mScrollbar->setVisible(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mScrollbar->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mVisibleEmojis = ctrlWidth / mEmojiWidth;
|
||||
S32 padding = (ctrlWidth - mVisibleEmojis * mEmojiWidth) / 2;
|
||||
mRenderRect.mLeft += padding;
|
||||
mRenderRect.mRight -= padding;
|
||||
if (mEmojiHeight > ctrlHeight)
|
||||
{
|
||||
mEmojiHeight = ctrlHeight;
|
||||
}
|
||||
mEmojiHeight = mRenderRect.getHeight();
|
||||
mRenderRect.stretch((mRenderRect.getWidth() - mVisibleEmojis * mEmojiWidth) / -2, 0);
|
||||
}
|
||||
|
||||
updateScrollPos();
|
||||
|
|
@ -326,23 +418,27 @@ void LLPanelEmojiComplete::updateConstraints()
|
|||
|
||||
void LLPanelEmojiComplete::updateScrollPos()
|
||||
{
|
||||
const size_t cntEmoji = mEmojis.size();
|
||||
if (mNoScroll || 0 == cntEmoji || cntEmoji < mVisibleEmojis || 0 == mCurSelected)
|
||||
{
|
||||
mScrollPos = 0;
|
||||
if (mCurSelected >= mVisibleEmojis)
|
||||
{
|
||||
mCurSelected = mVisibleEmojis ? mVisibleEmojis - 1 : 0;
|
||||
}
|
||||
}
|
||||
else if (cntEmoji - 1 == mCurSelected)
|
||||
{
|
||||
mScrollPos = mCurSelected - mVisibleEmojis + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mScrollPos = mCurSelected - ((float)mCurSelected / (cntEmoji - 2) * (mVisibleEmojis - 2));
|
||||
}
|
||||
if (mNoScroll || 0 == mTotalEmojis || mTotalEmojis < mVisibleEmojis || 0 == mCurSelected)
|
||||
{
|
||||
mScrollPos = 0;
|
||||
if (mCurSelected >= mVisibleEmojis)
|
||||
{
|
||||
mCurSelected = mVisibleEmojis ? mVisibleEmojis - 1 : 0;
|
||||
}
|
||||
}
|
||||
else if (mTotalEmojis - 1 == mCurSelected)
|
||||
{
|
||||
mScrollPos = mTotalEmojis - mVisibleEmojis;
|
||||
}
|
||||
else
|
||||
{
|
||||
mScrollPos = mCurSelected - ((float)mCurSelected / (mTotalEmojis - 2) * (mVisibleEmojis - 2));
|
||||
}
|
||||
|
||||
if (mScrollbar && mScrollbar->getVisible())
|
||||
{
|
||||
mScrollbar->setDocPos(mScrollPos);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
@ -350,33 +446,33 @@ void LLPanelEmojiComplete::updateScrollPos()
|
|||
//
|
||||
|
||||
LLFloaterEmojiComplete::LLFloaterEmojiComplete(const LLSD& sdKey)
|
||||
: LLFloater(sdKey)
|
||||
: LLFloater(sdKey)
|
||||
{
|
||||
// This floater should hover on top of our dependent (with the dependent having the focus)
|
||||
setFocusStealsFrontmost(false);
|
||||
setAutoFocus(false);
|
||||
setBackgroundVisible(false);
|
||||
setIsChrome(true);
|
||||
// This floater should hover on top of our dependent (with the dependent having the focus)
|
||||
setFocusStealsFrontmost(false);
|
||||
setAutoFocus(false);
|
||||
setBackgroundVisible(false);
|
||||
setIsChrome(true);
|
||||
}
|
||||
|
||||
BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent)
|
||||
{
|
||||
bool handled = false;
|
||||
if (MASK_NONE == mask)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KEY_ESCAPE:
|
||||
LLEmojiHelper::instance().hideHelper();
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool handled = false;
|
||||
if (MASK_NONE == mask)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KEY_ESCAPE:
|
||||
LLEmojiHelper::instance().hideHelper();
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (handled)
|
||||
return TRUE;
|
||||
if (handled)
|
||||
return TRUE;
|
||||
|
||||
return LLFloater::handleKey(key, mask, called_from_parent);
|
||||
return LLFloater::handleKey(key, mask, called_from_parent);
|
||||
}
|
||||
|
||||
void LLFloaterEmojiComplete::onOpen(const LLSD& key)
|
||||
|
|
@ -402,30 +498,33 @@ void LLFloaterEmojiComplete::onOpen(const LLSD& key)
|
|||
|
||||
BOOL LLFloaterEmojiComplete::postBuild()
|
||||
{
|
||||
mEmojiCtrl = findChild<LLPanelEmojiComplete>("emoji_complete_ctrl");
|
||||
mEmojiCtrl->setCommitCallback(
|
||||
std::bind([&](const LLSD& sdValue)
|
||||
{
|
||||
setValue(sdValue);
|
||||
onCommit();
|
||||
}, std::placeholders::_2));
|
||||
mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth();
|
||||
mEmojiCtrl = findChild<LLPanelEmojiComplete>("emoji_complete_ctrl");
|
||||
mEmojiCtrl->setCommitCallback(
|
||||
[this](LLUICtrl* ctrl, const LLSD& param)
|
||||
{
|
||||
setValue(param);
|
||||
onCommit();
|
||||
});
|
||||
|
||||
return LLFloater::postBuild();
|
||||
mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth();
|
||||
mEmojiCtrlVert = getRect().getHeight() - mEmojiCtrl->getRect().getHeight();
|
||||
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
|
||||
void LLFloaterEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
if (!called_from_parent)
|
||||
{
|
||||
LLRect rctFloater = getRect(), rctCtrl = mEmojiCtrl->getRect();
|
||||
rctFloater.mRight = rctFloater.mLeft + rctCtrl.getWidth() + mEmojiCtrlHorz;
|
||||
setRect(rctFloater);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LLFloater::reshape(width, height, called_from_parent);
|
||||
if (called_from_parent)
|
||||
{
|
||||
LLFloater::reshape(width, height, called_from_parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLRect outer(getRect()), inner(mEmojiCtrl->getRect());
|
||||
outer.mRight = outer.mLeft + inner.getWidth() + mEmojiCtrlHorz;
|
||||
outer.mTop = outer.mBottom + inner.getHeight() + mEmojiCtrlVert;
|
||||
setRect(outer);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -29,79 +29,83 @@
|
|||
#include "llfloater.h"
|
||||
#include "lluictrl.h"
|
||||
|
||||
class LLScrollbar;
|
||||
|
||||
// ============================================================================
|
||||
// LLPanelEmojiComplete
|
||||
//
|
||||
|
||||
class LLPanelEmojiComplete : public LLUICtrl
|
||||
{
|
||||
friend class LLUICtrlFactory;
|
||||
friend class LLUICtrlFactory;
|
||||
public:
|
||||
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
|
||||
{
|
||||
Optional<bool> autosize;
|
||||
Optional<bool> noscroll;
|
||||
Optional<bool> vertical;
|
||||
Optional<S32> max_emoji,
|
||||
padding;
|
||||
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
|
||||
{
|
||||
Optional<bool> autosize;
|
||||
Optional<bool> noscroll;
|
||||
Optional<bool> vertical;
|
||||
Optional<S32> max_visible,
|
||||
padding;
|
||||
|
||||
Optional<LLUIImage*> selected_image;
|
||||
Optional<LLUIImage*> selected_image;
|
||||
|
||||
Params();
|
||||
};
|
||||
Params();
|
||||
};
|
||||
|
||||
protected:
|
||||
LLPanelEmojiComplete(const LLPanelEmojiComplete::Params&);
|
||||
LLPanelEmojiComplete(const LLPanelEmojiComplete::Params&);
|
||||
|
||||
public:
|
||||
virtual ~LLPanelEmojiComplete();
|
||||
virtual ~LLPanelEmojiComplete();
|
||||
|
||||
void draw() override;
|
||||
BOOL handleHover(S32 x, S32 y, MASK mask) override;
|
||||
BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
|
||||
BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
|
||||
BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
|
||||
void onCommit() override;
|
||||
void reshape(S32 width, S32 height, BOOL called_from_parent) override;
|
||||
void draw() override;
|
||||
BOOL handleHover(S32 x, S32 y, MASK mask) override;
|
||||
BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
|
||||
BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
|
||||
BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
|
||||
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override;
|
||||
void onCommit() override;
|
||||
void reshape(S32 width, S32 height, BOOL called_from_parent) override;
|
||||
|
||||
public:
|
||||
const LLWString& getEmojis() const { return mEmojis; }
|
||||
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;
|
||||
const LLWString& getEmojis() const { return mEmojis; }
|
||||
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();
|
||||
size_t posToIndex(S32 x, S32 y) const;
|
||||
void select(size_t emoji_idx);
|
||||
void selectNext();
|
||||
void selectPrevious();
|
||||
void updateConstraints();
|
||||
void updateScrollPos();
|
||||
void onEmojisChanged();
|
||||
void onScrollbarChange(S32 index);
|
||||
size_t posToIndex(S32 x, S32 y) const;
|
||||
void select(size_t emoji_idx);
|
||||
void selectNext();
|
||||
void selectPrevious();
|
||||
void updateConstraints();
|
||||
void updateScrollPos();
|
||||
|
||||
protected:
|
||||
static constexpr auto npos = std::numeric_limits<size_t>::max();
|
||||
const bool mAutoSize;
|
||||
const bool mNoScroll;
|
||||
const bool mVertical;
|
||||
const size_t mMaxVisible;
|
||||
const S32 mPadding;
|
||||
const LLUIImagePtr mSelectedImage;
|
||||
const LLFontGL* mIconFont;
|
||||
const LLFontGL* mTextFont;
|
||||
|
||||
const bool mAutoSize = false;
|
||||
const bool mNoScroll = false;
|
||||
const bool mVertical = false;
|
||||
const size_t mMaxVisible = 0;
|
||||
const S32 mPadding = 8;
|
||||
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;
|
||||
size_t mCurSelected = 0;
|
||||
LLVector2 mLastHover;
|
||||
LLWString mEmojis;
|
||||
LLScrollbar* mScrollbar;
|
||||
LLRect mRenderRect;
|
||||
U16 mEmojiWidth = 0;
|
||||
U16 mEmojiHeight = 0;
|
||||
size_t mTotalEmojis = 0;
|
||||
size_t mVisibleEmojis = 0;
|
||||
size_t mFirstVisible = 0;
|
||||
size_t mScrollPos = 0;
|
||||
size_t mCurSelected = 0;
|
||||
LLVector2 mLastHover;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
|
@ -111,17 +115,18 @@ protected:
|
|||
class LLFloaterEmojiComplete : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterEmojiComplete(const LLSD& sdKey);
|
||||
LLFloaterEmojiComplete(const LLSD& sdKey);
|
||||
|
||||
public:
|
||||
BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
|
||||
void onOpen(const LLSD& key) override;
|
||||
BOOL postBuild() override;
|
||||
void reshape(S32 width, S32 height, BOOL called_from_parent) override;
|
||||
BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
|
||||
void onOpen(const LLSD& key) override;
|
||||
BOOL postBuild() override;
|
||||
void reshape(S32 width, S32 height, BOOL called_from_parent) override;
|
||||
|
||||
protected:
|
||||
LLPanelEmojiComplete* mEmojiCtrl = nullptr;
|
||||
S32 mEmojiCtrlHorz = 0;
|
||||
LLPanelEmojiComplete* mEmojiCtrl = nullptr;
|
||||
S32 mEmojiCtrlHorz = 0;
|
||||
S32 mEmojiCtrlVert = 0;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
name="emoji_complete"
|
||||
single_instance="true"
|
||||
layout="topleft"
|
||||
bg_opaque_image="Window_NoTitle_Foreground"
|
||||
bg_alpha_image="Window_NoTitle_Background"
|
||||
can_close="false"
|
||||
can_dock="false"
|
||||
can_drag_on_left="false"
|
||||
|
|
@ -11,6 +13,7 @@
|
|||
can_tear_off="false"
|
||||
header_height="0"
|
||||
legacy_header_height="0"
|
||||
show_title="false"
|
||||
width="240"
|
||||
height="40"
|
||||
>
|
||||
|
|
@ -20,7 +23,8 @@
|
|||
layout="topleft"
|
||||
autosize="true"
|
||||
vertical="true"
|
||||
max_emoji="7"
|
||||
max_visible="7"
|
||||
padding="4"
|
||||
width="230"
|
||||
height="30"
|
||||
left="5"
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@
|
|||
name="emoji_recent_icons_ctrl"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
max_emoji="20"
|
||||
max_visible="20"
|
||||
top="0"
|
||||
left="1"
|
||||
right="-65"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
autosize="false"
|
||||
hover_image="ListItem_Over"
|
||||
selected_image="ListItem_Select"
|
||||
max_emoji="7"
|
||||
max_visible="7"
|
||||
padding="8"
|
||||
>
|
||||
</emoji_complete>
|
||||
|
|
|
|||
Loading…
Reference in New Issue