diff options
Diffstat (limited to 'indra/newview/llfloateremojipicker.cpp')
-rw-r--r-- | indra/newview/llfloateremojipicker.cpp | 203 |
1 files changed, 178 insertions, 25 deletions
diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index a63a9fac4f..5efd2a24c0 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -27,10 +27,18 @@ #include "llfloateremojipicker.h" +#include "llcombobox.h" +#include "llemojidictionary.h" #include "llfloaterreg.h" +#include "lllineeditor.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" -#include "llemojidictionary.h" +#include "lltextbox.h" +#include "llviewerchat.h" + +std::string LLFloaterEmojiPicker::mSelectedCategory; +std::string LLFloaterEmojiPicker::mSearchPattern; +int LLFloaterEmojiPicker::mSelectedEmojiIndex; class LLEmojiScrollListItem : public LLScrollListItem { @@ -69,17 +77,18 @@ LLFloaterEmojiPicker* LLFloaterEmojiPicker::getInstance() return floater; } -LLFloaterEmojiPicker* LLFloaterEmojiPicker::showInstance(select_callback_t callback) +LLFloaterEmojiPicker* LLFloaterEmojiPicker::showInstance(pick_callback_t pick_callback, close_callback_t close_callback) { LLFloaterEmojiPicker* floater = getInstance(); if (LLFloaterEmojiPicker* floater = getInstance()) - floater->show(callback); + floater->show(pick_callback, close_callback); return floater; } -void LLFloaterEmojiPicker::show(select_callback_t callback) +void LLFloaterEmojiPicker::show(pick_callback_t pick_callback, close_callback_t close_callback) { - mSelectCallback = callback; + mEmojiPickCallback = pick_callback; + mFloaterCloseCallback = close_callback; openFloater(mKey); setFocus(TRUE); } @@ -91,19 +100,41 @@ LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key) BOOL LLFloaterEmojiPicker::postBuild() { - if ((mEmojis = getChild<LLScrollListCtrl>("Emojis"))) + // Should be initialized first + if ((mPreviewEmoji = getChild<LLButton>("PreviewEmoji"))) { - mEmojis->setDoubleClickCallback(boost::bind(&LLFloaterEmojiPicker::onSelect, this)); - - mEmojis->clearRows(); + mPreviewEmoji->setClickedCallback(boost::bind(&LLFloaterEmojiPicker::onPreviewEmojiClick, this)); + } - const std::map<llwchar, const LLEmojiDescriptor*>& emoji2Descr = LLEmojiDictionary::instance().getEmoji2Descr(); - for (const std::pair<const llwchar, const LLEmojiDescriptor*>& it : emoji2Descr) + if ((mCategory = getChild<LLComboBox>("Category"))) + { + mCategory->setCommitCallback(boost::bind(&LLFloaterEmojiPicker::onCategoryCommit, this)); + mCategory->setLabel(LLStringExplicit("Choose a category")); + const auto& cat2Descrs = LLEmojiDictionary::instance().getCategory2Descrs(); + mCategory->clearRows(); + for (const auto& item : cat2Descrs) { - LLScrollListItem::Params params; - params.columns.add().column("name").value(it.second->Name); - mEmojis->addRow(new LLEmojiScrollListItem(it.first, params), params); + std::string value = item.first; + std::string name = value; + LLStringUtil::capitalize(name); + mCategory->add(name, value); } + mCategory->setSelectedByValue(mSelectedCategory, true); + } + + if ((mSearch = getChild<LLLineEditor>("Search"))) + { + mSearch->setKeystrokeCallback(boost::bind(&LLFloaterEmojiPicker::onSearchKeystroke, this, _1, _2), NULL); + mSearch->setLabel(LLStringExplicit("Type to search an emoji")); + mSearch->setFont(LLViewerChat::getChatFont()); + mSearch->setText(mSearchPattern); + } + + if ((mEmojis = getChild<LLScrollListCtrl>("Emojis"))) + { + mEmojis->setCommitCallback(boost::bind(&LLFloaterEmojiPicker::onEmojiSelect, this)); + mEmojis->setDoubleClickCallback(boost::bind(&LLFloaterEmojiPicker::onEmojiPick, this)); + fillEmojis(); } return TRUE; @@ -114,30 +145,152 @@ LLFloaterEmojiPicker::~LLFloaterEmojiPicker() gFocusMgr.releaseFocusIfNeeded( this ); } -void LLFloaterEmojiPicker::onSelect() +void LLFloaterEmojiPicker::fillEmojis() +{ + mEmojis->clearRows(); + + const auto& emoji2Descr = LLEmojiDictionary::instance().getEmoji2Descr(); + for (const std::pair<const llwchar, const LLEmojiDescriptor*>& it : emoji2Descr) + { + const LLEmojiDescriptor* descr = it.second; + + if (!mSelectedCategory.empty() && !matchesCategory(descr)) + continue; + + if (!mSearchPattern.empty() && !matchesPattern(descr)) + continue; + + LLScrollListItem::Params params; + params.columns.add().column("name").value(descr->Name); + mEmojis->addRow(new LLEmojiScrollListItem(it.first, params), params); + } + + if (mEmojis->getItemCount()) + { + if (mSelectedEmojiIndex > 0 && mSelectedEmojiIndex < mEmojis->getItemCount()) + mEmojis->selectNthItem(mSelectedEmojiIndex); + else + mEmojis->selectFirstItem(); + + mEmojis->scrollToShowSelected(); + } + else + { + onEmojiEmpty(); + } +} + +bool LLFloaterEmojiPicker::matchesCategory(const LLEmojiDescriptor* descr) +{ + return std::find(descr->Categories.begin(), descr->Categories.end(), mSelectedCategory) != descr->Categories.end(); +} + +bool LLFloaterEmojiPicker::matchesPattern(const LLEmojiDescriptor* descr) +{ + if (descr->Name.find(mSearchPattern) != std::string::npos) + return true; + for (auto shortCode : descr->ShortCodes) + if (shortCode.find(mSearchPattern) != std::string::npos) + return true; + for (auto category : descr->Categories) + if (category.find(mSearchPattern) != std::string::npos) + return true; + return false; +} + +void LLFloaterEmojiPicker::onCategoryCommit() +{ + mSelectedCategory = mCategory->getSelectedValue().asString(); + mSelectedEmojiIndex = 0; + fillEmojis(); +} + +void LLFloaterEmojiPicker::onSearchKeystroke(LLLineEditor* caller, void* user_data) { - if (mEmojis && mSelectCallback) + mSearchPattern = mSearch->getText(); + mSelectedEmojiIndex = 0; + fillEmojis(); +} + +void LLFloaterEmojiPicker::onPreviewEmojiClick() +{ + if (mEmojis && mEmojiPickCallback) { if (LLEmojiScrollListItem* item = dynamic_cast<LLEmojiScrollListItem*>(mEmojis->getFirstSelected())) { - mSelectCallback(item->getEmoji()); + mEmojiPickCallback(item->getEmoji()); } } } -// virtual -BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask) +void LLFloaterEmojiPicker::onEmojiSelect() { - if (key == KEY_RETURN && mask == MASK_NONE) + const LLEmojiScrollListItem* item = dynamic_cast<LLEmojiScrollListItem*>(mEmojis->getFirstSelected()); + if (item) { - onSelect(); - return TRUE; + mSelectedEmojiIndex = mEmojis->getFirstSelectedIndex(); + LLUIString text; + text.insert(0, LLWString(1, item->getEmoji())); + if (mPreviewEmoji) + mPreviewEmoji->setLabel(text); + return; } - else if (key == KEY_ESCAPE && mask == MASK_NONE) + + onEmojiEmpty(); +} + +void LLFloaterEmojiPicker::onEmojiEmpty() +{ + mSelectedEmojiIndex = 0; + if (mPreviewEmoji) + mPreviewEmoji->setLabel(LLUIString()); +} + +void LLFloaterEmojiPicker::onEmojiPick() +{ + if (mEmojis && mEmojiPickCallback) { - closeFloater(); - return TRUE; + if (LLEmojiScrollListItem* item = dynamic_cast<LLEmojiScrollListItem*>(mEmojis->getFirstSelected())) + { + mEmojiPickCallback(item->getEmoji()); + closeFloater(); + } + } +} + +// virtual +BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask) +{ + if (mask == MASK_NONE) + { + switch (key) + { + case KEY_RETURN: + if (mCategory->hasFocus()) + break; + onEmojiPick(); + return TRUE; + case KEY_ESCAPE: + closeFloater(); + return TRUE; + case KEY_UP: + mEmojis->selectPrevItem(); + mEmojis->scrollToShowSelected(); + return TRUE; + case KEY_DOWN: + mEmojis->selectNextItem(); + mEmojis->scrollToShowSelected(); + return TRUE; + } } return LLFloater::handleKeyHere(key, mask); } + +// virtual +void LLFloaterEmojiPicker::closeFloater(bool app_quitting) +{ + LLFloater::closeFloater(app_quitting); + if (mFloaterCloseCallback) + mFloaterCloseCallback(); +} |