diff options
author | Alexander Gavriliuk <alexandrgproductengine@lindenlab.com> | 2023-07-06 23:48:06 +0200 |
---|---|---|
committer | Guru <alexandrgproductengine@lindenlab.com> | 2023-07-07 00:22:34 +0200 |
commit | 9793308a600c1e1ce35ec727ed6341e7668848ea (patch) | |
tree | 17d47429881ed210f341695fb83475a488782170 /indra/newview | |
parent | 4abecaa04bd003136ed027e3892a2ca13d895936 (diff) |
SL-19951 Organize emoji categories in groups
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/app_settings/emoji_groups.xml | 82 | ||||
-rw-r--r-- | indra/newview/llfloateremojipicker.cpp | 849 | ||||
-rw-r--r-- | indra/newview/llfloateremojipicker.h | 102 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/da/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/de/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_emoji_picker.xml | 33 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/es/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/fr/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/it/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/ja/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/pl/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/pt/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/ru/emoji_categories.xml | 59 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/zh/emoji_categories.xml | 59 |
15 files changed, 1284 insertions, 431 deletions
diff --git a/indra/newview/app_settings/emoji_groups.xml b/indra/newview/app_settings/emoji_groups.xml new file mode 100644 index 0000000000..b433927f91 --- /dev/null +++ b/indra/newview/app_settings/emoji_groups.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>all</string> + <key>Character</key> + <string>🔍</string> + </map> + <map> + <key>Character</key> + <string>😀</string> + <key>Categories</key> + <array> + <string>smileys and emotion</string> + <string>people and body</string> + </array> + </map> + <map> + <key>Character</key> + <string>🥬</string> + <key>Categories</key> + <array> + <string>animals and nature</string> + </array> + </map> + <map> + <key>Character</key> + <string>🍔</string> + <key>Categories</key> + <array> + <string>food and drink</string> + </array> + </map> + <map> + <key>Character</key> + <string>🛩</string> + <key>Categories</key> + <array> + <string>travel and places</string> + </array> + </map> + <map> + <key>Character</key> + <string>🏈</string> + <key>Categories</key> + <array> + <string>activities</string> + </array> + </map> + <map> + <key>Character</key> + <string>💡</string> + <key>Categories</key> + <array> + <string>objects</string> + </array> + </map> + <map> + <key>Character</key> + <string>⚠</string> + <key>Categories</key> + <array> + <string>symbols</string> + </array> + </map> + <map> + <key>Name</key> + <string>others</string> + <key>Character</key> + <string>🌂</string> + </map> + <map> + <key>Name</key> + <string>skip</string> + <key>Categories</key> + <array> + <string>components</string> + </array> + </map> + </array> +</llsd> diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index f63062f03a..9194a49c45 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -27,6 +27,7 @@ #include "llfloateremojipicker.h" +#include "llbutton.h" #include "llcombobox.h" #include "llemojidictionary.h" #include "llfloaterreg.h" @@ -39,179 +40,179 @@ #include "lltextbox.h" #include "llviewerchat.h" -std::string LLFloaterEmojiPicker::mSelectedCategory; -std::string LLFloaterEmojiPicker::mSearchPattern; +size_t LLFloaterEmojiPicker::sSelectedGroupIndex; +std::string LLFloaterEmojiPicker::sSearchPattern; class LLEmojiScrollListItem : public LLScrollListItem { public: - LLEmojiScrollListItem(const llwchar emoji, const LLScrollListItem::Params& params) - : LLScrollListItem(params) - , mEmoji(emoji) - { - } - - llwchar getEmoji() const { return mEmoji; } - - virtual void draw(const LLRect& rect, - const LLColor4& fg_color, - const LLColor4& hover_color, // highlight/hover selection of whole item or cell - const LLColor4& select_color, // highlight/hover selection of whole item or cell - const LLColor4& highlight_color, // highlights contents of cells (ex: text) - S32 column_padding) override - { - LLScrollListItem::draw(rect, fg_color, hover_color, select_color, highlight_color, column_padding); - - LLWString wstr(1, mEmoji); - S32 width = getColumn(0)->getWidth(); - F32 x = rect.mLeft + width / 2; - F32 y = rect.getCenterY(); - LLFontGL::getFontEmoji()->render( - wstr, // wstr - 0, // begin_offset - x, // x - y, // y - LLColor4::white, // color - LLFontGL::HCENTER, // halign - LLFontGL::VCENTER, // valign - LLFontGL::NORMAL, // style - LLFontGL::DROP_SHADOW_SOFT, // shadow - 1, // max_chars - S32_MAX, // max_pixels - nullptr, // right_x - false, // use_ellipses - true); // use_color - } + LLEmojiScrollListItem(const llwchar emoji, const LLScrollListItem::Params& params) + : LLScrollListItem(params) + , mEmoji(emoji) + { + } + + llwchar getEmoji() const { return mEmoji; } + + virtual void draw(const LLRect& rect, + const LLColor4& fg_color, + const LLColor4& hover_color, // highlight/hover selection of whole item or cell + const LLColor4& select_color, // highlight/hover selection of whole item or cell + const LLColor4& highlight_color, // highlights contents of cells (ex: text) + S32 column_padding) override + { + LLScrollListItem::draw(rect, fg_color, hover_color, select_color, highlight_color, column_padding); + + LLWString wstr(1, mEmoji); + S32 width = getColumn(0)->getWidth(); + F32 x = rect.mLeft + width / 2; + F32 y = rect.getCenterY(); + LLFontGL::getFontEmoji()->render( + wstr, // wstr + 0, // begin_offset + x, // x + y, // y + LLColor4::white, // color + LLFontGL::HCENTER, // halign + LLFontGL::VCENTER, // valign + LLFontGL::NORMAL, // style + LLFontGL::DROP_SHADOW_SOFT, // shadow + 1, // max_chars + S32_MAX, // max_pixels + nullptr, // right_x + false, // use_ellipses + true); // use_color + } private: - llwchar mEmoji; + llwchar mEmoji; }; class LLEmojiGridRow : public LLScrollingPanel { public: - LLEmojiGridRow(const LLPanel::Params& panel_params, - const LLScrollingPanelList::Params& list_params) - : LLScrollingPanel(panel_params) - , mList(new LLScrollingPanelList(list_params)) - { - addChild(mList); - } + LLEmojiGridRow(const LLPanel::Params& panel_params, + const LLScrollingPanelList::Params& list_params) + : LLScrollingPanel(panel_params) + , mList(new LLScrollingPanelList(list_params)) + { + addChild(mList); + } - virtual void updatePanel(BOOL allow_modify) override {} + virtual void updatePanel(BOOL allow_modify) override {} public: - LLScrollingPanelList* mList; + LLScrollingPanelList* mList; }; class LLEmojiGridDivider : public LLScrollingPanel { public: - LLEmojiGridDivider(const LLPanel::Params& panel_params, std::string text) - : LLScrollingPanel(panel_params) - , mText(utf8string_to_wstring(text)) - { - } - - virtual void draw() override - { - LLScrollingPanel::draw(); - - F32 x = 4; // padding-left - F32 y = getRect().getHeight() / 2; - LLFontGL::getFontSansSerifBold()->render( - mText, // wstr - 0, // begin_offset - x, // x - y, // y - LLColor4::white, // color - LLFontGL::LEFT, // halign - LLFontGL::VCENTER, // valign - LLFontGL::NORMAL, // style - LLFontGL::DROP_SHADOW_SOFT, // shadow - mText.size(), // max_chars - S32_MAX, // max_pixels - nullptr, // right_x - false, // use_ellipses - true); // use_color - } - - virtual void updatePanel(BOOL allow_modify) override {} + LLEmojiGridDivider(const LLPanel::Params& panel_params, std::string text) + : LLScrollingPanel(panel_params) + , mText(utf8string_to_wstring(text)) + { + } + + virtual void draw() override + { + LLScrollingPanel::draw(); + + F32 x = 4; // padding-left + F32 y = getRect().getHeight() / 2; + LLFontGL::getFontSansSerifBold()->render( + mText, // wstr + 0, // begin_offset + x, // x + y, // y + LLColor4::white, // color + LLFontGL::LEFT, // halign + LLFontGL::VCENTER, // valign + LLFontGL::NORMAL, // style + LLFontGL::DROP_SHADOW_SOFT, // shadow + mText.size(), // max_chars + S32_MAX, // max_pixels + nullptr, // right_x + false, // use_ellipses + true); // use_color + } + + virtual void updatePanel(BOOL allow_modify) override {} private: - const LLWString mText; + const LLWString mText; }; class LLEmojiGridIcon : public LLScrollingPanel { public: - LLEmojiGridIcon(const LLPanel::Params& panel_params, const LLEmojiDescriptor* descr, std::string category) - : LLScrollingPanel(panel_params) - , mEmoji(descr->Character) - , mText(LLWString(1, mEmoji)) - , mDescr(descr->Name) - , mCategory(category) - { - } - - virtual void draw() override - { - LLScrollingPanel::draw(); - - F32 x = getRect().getWidth() / 2; - F32 y = getRect().getHeight() / 2; - LLFontGL::getFontEmoji()->render( - mText, // wstr - 0, // begin_offset - x, // x - y, // y - LLColor4::white, // color - LLFontGL::HCENTER, // halign - LLFontGL::VCENTER, // valign - LLFontGL::NORMAL, // style - LLFontGL::DROP_SHADOW_SOFT, // shadow - 1, // max_chars - S32_MAX, // max_pixels - nullptr, // right_x - false, // use_ellipses - true); // use_color - } - - virtual void updatePanel(BOOL allow_modify) override {} - - llwchar getEmoji() const { return mEmoji; } - LLWString getText() const { return mText; } - std::string getDescr() const { return mDescr; } - std::string getCategory() const { return mCategory; } + LLEmojiGridIcon(const LLPanel::Params& panel_params, const LLEmojiDescriptor* descr, std::string category) + : LLScrollingPanel(panel_params) + , mEmoji(descr->Character) + , mText(LLWString(1, mEmoji)) + , mDescr(descr->getShortCodes()) + , mCategory(category) + { + } + + virtual void draw() override + { + LLScrollingPanel::draw(); + + F32 x = getRect().getWidth() / 2; + F32 y = getRect().getHeight() / 2; + LLFontGL::getFontEmoji()->render( + mText, // wstr + 0, // begin_offset + x, // x + y, // y + LLColor4::white, // color + LLFontGL::HCENTER, // halign + LLFontGL::VCENTER, // valign + LLFontGL::NORMAL, // style + LLFontGL::DROP_SHADOW_SOFT, // shadow + 1, // max_chars + S32_MAX, // max_pixels + nullptr, // right_x + false, // use_ellipses + true); // use_color + } + + virtual void updatePanel(BOOL allow_modify) override {} + + llwchar getEmoji() const { return mEmoji; } + LLWString getText() const { return mText; } + std::string getDescr() const { return mDescr; } + std::string getCategory() const { return mCategory; } private: - const llwchar mEmoji; - const LLWString mText; - const std::string mDescr; - const std::string mCategory; + const llwchar mEmoji; + const LLWString mText; + const std::string mDescr; + const std::string mCategory; }; LLFloaterEmojiPicker* LLFloaterEmojiPicker::getInstance() { - LLFloaterEmojiPicker* floater = LLFloaterReg::getTypedInstance<LLFloaterEmojiPicker>("emoji_picker"); - if (!floater) - LL_ERRS() << "Cannot instantiate emoji picker" << LL_ENDL; - return floater; + LLFloaterEmojiPicker* floater = LLFloaterReg::getTypedInstance<LLFloaterEmojiPicker>("emoji_picker"); + if (!floater) + LL_ERRS() << "Cannot instantiate emoji picker" << LL_ENDL; + return floater; } LLFloaterEmojiPicker* LLFloaterEmojiPicker::showInstance(pick_callback_t pick_callback, close_callback_t close_callback) { - LLFloaterEmojiPicker* floater = getInstance(); - floater->show(pick_callback, close_callback); - return floater; + LLFloaterEmojiPicker* floater = getInstance(); + floater->show(pick_callback, close_callback); + return floater; } void LLFloaterEmojiPicker::show(pick_callback_t pick_callback, close_callback_t close_callback) { - mEmojiPickCallback = pick_callback; - mFloaterCloseCallback = close_callback; - openFloater(mKey); - setFocus(TRUE); + mEmojiPickCallback = pick_callback; + mFloaterCloseCallback = close_callback; + openFloater(mKey); + setFocus(TRUE); } LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key) @@ -221,313 +222,415 @@ LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key) BOOL LLFloaterEmojiPicker::postBuild() { - // Should be initialized first - mPreviewEmoji = getChild<LLButton>("PreviewEmoji"); - mPreviewEmoji->setClickedCallback([this](LLUICtrl*, const LLSD&) { onPreviewEmojiClick(); }); - - mDescription = getChild<LLTextBox>("Description"); - mDescription->setVisible(FALSE); - - mCategory = getChild<LLComboBox>("Category"); - mCategory->setCommitCallback([this](LLUICtrl*, const LLSD&) { onCategoryCommit(); }); - const LLEmojiDictionary::cat2descrs_map_t& cat2Descrs = LLEmojiDictionary::instance().getCategory2Descrs(); - mCategory->clearRows(); - for (const LLEmojiDictionary::cat2descrs_item_t& item : cat2Descrs) - { - std::string value = item.first; - std::string name = value; - LLStringUtil::capitalize(name); - mCategory->add(name, value); - } - mCategory->setSelectedByValue(mSelectedCategory, true); - - mSearch = getChild<LLLineEditor>("Search"); - mSearch->setKeystrokeCallback([this](LLLineEditor*, void*) { onSearchKeystroke(); }, NULL); - mSearch->setFont(LLViewerChat::getChatFont()); - mSearch->setText(mSearchPattern); - - mEmojiScroll = getChild<LLScrollContainer>("EmojiGridContainer"); - mEmojiScroll->setMouseEnterCallback([this](LLUICtrl*, const LLSD&) { onGridMouseEnter(); }); - mEmojiScroll->setMouseLeaveCallback([this](LLUICtrl*, const LLSD&) { onGridMouseLeave(); }); - - mEmojiGrid = getChild<LLScrollingPanelList>("EmojiGrid"); - - fillEmojiGrid(); - - return TRUE; + // Should be initialized first + mPreviewEmoji = getChild<LLButton>("PreviewEmoji"); + mPreviewEmoji->setClickedCallback([this](LLUICtrl*, const LLSD&) { onPreviewEmojiClick(); }); + + mDescription = getChild<LLTextBox>("Description"); + mDescription->setVisible(FALSE); + + mGroups = getChild<LLPanel>("Groups"); + mBadge = getChild<LLPanel>("Badge"); + + mSearch = getChild<LLLineEditor>("Search"); + mSearch->setKeystrokeCallback([this](LLLineEditor*, void*) { onSearchKeystroke(); }, NULL); + mSearch->setFont(LLViewerChat::getChatFont()); + mSearch->setText(sSearchPattern); + + mEmojiScroll = getChild<LLScrollContainer>("EmojiGridContainer"); + mEmojiScroll->setMouseEnterCallback([this](LLUICtrl*, const LLSD&) { onGridMouseEnter(); }); + mEmojiScroll->setMouseLeaveCallback([this](LLUICtrl*, const LLSD&) { onGridMouseLeave(); }); + + mEmojiGrid = getChild<LLScrollingPanelList>("EmojiGrid"); + + fillGroups(); + fillEmojis(); + + return TRUE; } void LLFloaterEmojiPicker::dirtyRect() { - super::dirtyRect(); + super::dirtyRect(); - if (mEmojiScroll && mEmojiScroll->getRect().getWidth() != mRecentGridWidth) - { - fillEmojiGrid(); - } + if (mEmojiScroll && mEmojiScroll->getRect().getWidth() != mRecentGridWidth) + { + moveGroups(); + fillEmojis(true); + } } LLFloaterEmojiPicker::~LLFloaterEmojiPicker() { - gFocusMgr.releaseFocusIfNeeded( this ); + gFocusMgr.releaseFocusIfNeeded( this ); +} + +void LLFloaterEmojiPicker::fillGroups() +{ + LLButton::Params params; + params.font = LLFontGL::getFontEmoji(); + //params.use_font_color = true; + + LLRect rect; + rect.mTop = mGroups->getRect().getHeight(); + rect.mBottom = mBadge->getRect().getHeight(); + + const std::vector<LLEmojiGroup>& groups = LLEmojiDictionary::instance().getGroups(); + for (const LLEmojiGroup& group : groups) + { + LLButton* button = LLUICtrlFactory::create<LLButton>(params); + button->setClickedCallback([this](LLUICtrl* ctrl, const LLSD&) { onGroupButtonClick(ctrl); }); + button->setMouseEnterCallback([this](LLUICtrl* ctrl, const LLSD&) { onGroupButtonMouseEnter(ctrl); }); + button->setMouseLeaveCallback([this](LLUICtrl* ctrl, const LLSD&) { onGroupButtonMouseLeave(ctrl); }); + + button->setRect(rect); + + LLUIString text; + text.insert(0, LLWString(1, group.Character)); + button->setLabel(text); + + if (mGroupButtons.size() == sSelectedGroupIndex) + { + button->setToggleState(TRUE); + } + + mGroupButtons.push_back(button); + mGroups->addChild(button); + } + + moveGroups(); +} + +void LLFloaterEmojiPicker::moveGroups() +{ + const std::vector<LLEmojiGroup>& groups = LLEmojiDictionary::instance().getGroups(); + if (groups.empty()) + return; + + int badgeWidth = mGroups->getRect().getWidth() / groups.size(); + if (badgeWidth == mRecentBadgeWidth) + return; + + mRecentBadgeWidth = badgeWidth; + + for (int i = 0; i < mGroupButtons.size(); ++i) + { + LLRect rect = mGroupButtons[i]->getRect(); + rect.mLeft = badgeWidth * i; + rect.mRight = rect.mLeft + badgeWidth; + mGroupButtons[i]->setRect(rect); + } + + LLRect rect = mBadge->getRect(); + rect.mLeft = badgeWidth * sSelectedGroupIndex; + rect.mRight = rect.mLeft + badgeWidth; + mBadge->setRect(rect); } -void LLFloaterEmojiPicker::fillEmojiGrid() +void LLFloaterEmojiPicker::fillEmojis(bool fromResize) { - mRecentGridWidth = mEmojiScroll->getRect().getWidth(); - - S32 scrollbarSize = mEmojiScroll->getSize(); - if (scrollbarSize < 0) - { - static LLUICachedControl<S32> scrollbar_size_control("UIScrollbarSize", 0); - scrollbarSize = scrollbar_size_control; - } - - const S32 clientWidth = mRecentGridWidth - scrollbarSize - mEmojiScroll->getBorderWidth() * 2; - const S32 gridPadding = mEmojiGrid->getPadding(); - const S32 iconSpacing = mEmojiGrid->getSpacing(); - const S32 rowWidth = clientWidth - gridPadding * 2; - const S32 iconSize = 28; // icon width and height - const S32 maxIcons = llmax(1, (rowWidth + iconSpacing) / (iconSize + iconSpacing)); - - // Optimization: don't rearrange for different widths with the same maxIcons - if (maxIcons == mRecentMaxIcons) - return; - mRecentMaxIcons = maxIcons; - - mHoveredIcon = nullptr; - mEmojiGrid->clearPanels(); - mPreviewEmoji->setLabel(LLUIString()); - - if (mEmojiGrid->getRect().getWidth() != clientWidth) - { - LLRect rect = mEmojiGrid->getRect(); - rect.mRight = rect.mLeft + clientWidth; - mEmojiGrid->setRect(rect); - } - - LLPanel::Params row_panel_params; - row_panel_params.rect = LLRect(0, iconSize, rowWidth, 0); - - LLScrollingPanelList::Params row_list_params; - row_list_params.rect = row_panel_params.rect; - row_list_params.is_horizontal = TRUE; - row_list_params.padding = 0; - row_list_params.spacing = iconSpacing; - - LLPanel::Params icon_params; - LLRect icon_rect(0, iconSize, iconSize, 0); - - static const LLColor4 bgcolors[] = - { - LLColor4(0.8f, 0.6f, 0.8f, 1.0f), - LLColor4(0.8f, 0.8f, 0.4f, 1.0f), - LLColor4(0.6f, 0.6f, 0.8f, 1.0f), - LLColor4(0.4f, 0.7f, 0.4f, 1.0f), - LLColor4(0.5f, 0.7f, 0.9f, 1.0f), - LLColor4(0.7f, 0.8f, 0.2f, 1.0f) - }; - - static constexpr U32 bgcolorCount = sizeof(bgcolors) / sizeof(*bgcolors); - - auto listCategory = [&](std::string category, const std::vector<const LLEmojiDescriptor*>& emojis, bool showDivider) - { - int iconIndex = 0; - LLEmojiGridRow* row = nullptr; - LLStringUtil::capitalize(category); - for (const LLEmojiDescriptor* descr : emojis) - { - if (mSearchPattern.empty() || matchesPattern(descr)) - { - // Place a category title if needed - if (showDivider) - { - LLEmojiGridDivider* div = new LLEmojiGridDivider(row_panel_params, category); - mEmojiGrid->addPanel(div, true); - showDivider = false; - } - - // Place a new row each (maxIcons) icons - if (!(iconIndex % maxIcons)) - { - row = new LLEmojiGridRow(row_panel_params, row_list_params); - mEmojiGrid->addPanel(row, true); - } - - // Place a new icon to the current row - LLEmojiGridIcon* icon = new LLEmojiGridIcon(icon_params, descr, category); - icon->setMouseEnterCallback([this](LLUICtrl* ctrl, const LLSD&) { onEmojiMouseEnter(ctrl); }); - icon->setMouseLeaveCallback([this](LLUICtrl* ctrl, const LLSD&) { onEmojiMouseLeave(ctrl); }); - icon->setMouseUpCallback([this](LLUICtrl* ctrl, S32, S32, MASK mask) { onEmojiMouseClick(ctrl, mask); }); - icon->setBackgroundColor(bgcolors[iconIndex % bgcolorCount]); - icon->setBackgroundOpaque(1); - icon->setRect(icon_rect); - row->mList->addPanel(icon, true); - - iconIndex++; - } - } - }; - - const LLEmojiDictionary::cat2descrs_map_t& category2Descr = LLEmojiDictionary::instance().getCategory2Descrs(); - if (mSelectedCategory.empty()) - { - // List all categories with titles - for (const LLEmojiDictionary::cat2descrs_item_t& item : category2Descr) - { - listCategory(item.first, item.second, TRUE); - } - } - else - { - // List one category without title - const LLEmojiDictionary::cat2descrs_map_t::const_iterator& item = category2Descr.find(mSelectedCategory); - if (item != category2Descr.end()) - { - listCategory(mSelectedCategory, item->second, FALSE); - } - } + mRecentGridWidth = mEmojiScroll->getRect().getWidth(); + + S32 scrollbarSize = mEmojiScroll->getSize(); + if (scrollbarSize < 0) + { + static LLUICachedControl<S32> scrollbar_size_control("UIScrollbarSize", 0); + scrollbarSize = scrollbar_size_control; + } + + const S32 clientWidth = mRecentGridWidth - scrollbarSize - mEmojiScroll->getBorderWidth() * 2; + const S32 gridPadding = mEmojiGrid->getPadding(); + const S32 iconSpacing = mEmojiGrid->getSpacing(); + const S32 rowWidth = clientWidth - gridPadding * 2; + const S32 iconSize = 28; // icon width and height + const S32 maxIcons = llmax(1, (rowWidth + iconSpacing) / (iconSize + iconSpacing)); + + // Optimization: don't rearrange for different widths with the same maxIcons + if (fromResize && (maxIcons == mRecentMaxIcons)) + return; + + mRecentMaxIcons = maxIcons; + + mHoveredIcon = nullptr; + mEmojiGrid->clearPanels(); + mPreviewEmoji->setLabel(LLUIString()); + + if (mEmojiGrid->getRect().getWidth() != clientWidth) + { + LLRect rect = mEmojiGrid->getRect(); + rect.mRight = rect.mLeft + clientWidth; + mEmojiGrid->setRect(rect); + } + + LLPanel::Params row_panel_params; + row_panel_params.rect = LLRect(0, iconSize, rowWidth, 0); + + LLScrollingPanelList::Params row_list_params; + row_list_params.rect = row_panel_params.rect; + row_list_params.is_horizontal = TRUE; + row_list_params.padding = 0; + row_list_params.spacing = iconSpacing; + + LLPanel::Params icon_params; + LLRect icon_rect(0, iconSize, iconSize, 0); + + static const LLColor4 bgcolors[] = + { + LLColor4(0.8f, 0.6f, 0.8f, 1.0f), + LLColor4(0.8f, 0.8f, 0.4f, 1.0f), + LLColor4(0.6f, 0.6f, 0.8f, 1.0f), + LLColor4(0.4f, 0.7f, 0.4f, 1.0f), + LLColor4(0.5f, 0.7f, 0.9f, 1.0f), + LLColor4(0.7f, 0.8f, 0.2f, 1.0f) + }; + + static constexpr U32 bgcolorCount = sizeof(bgcolors) / sizeof(*bgcolors); + + auto listCategory = [&](std::string category, const std::vector<const LLEmojiDescriptor*>& emojis) + { + int iconIndex = 0; + bool showDivider = true; + LLEmojiGridRow* row = nullptr; + LLStringUtil::capitalize(category); + for (const LLEmojiDescriptor* descr : emojis) + { + if (sSearchPattern.empty() || matchesPattern(descr)) + { + // Place a category title if needed + if (showDivider) + { + LLEmojiGridDivider* div = new LLEmojiGridDivider(row_panel_params, category); + mEmojiGrid->addPanel(div, true); + showDivider = false; + } + + // Place a new row each (maxIcons) icons + if (!(iconIndex % maxIcons)) + { + row = new LLEmojiGridRow(row_panel_params, row_list_params); + mEmojiGrid->addPanel(row, true); + } + + // Place a new icon to the current row + LLEmojiGridIcon* icon = new LLEmojiGridIcon(icon_params, descr, category); + icon->setMouseEnterCallback([this](LLUICtrl* ctrl, const LLSD&) { onEmojiMouseEnter(ctrl); }); + icon->setMouseLeaveCallback([this](LLUICtrl* ctrl, const LLSD&) { onEmojiMouseLeave(ctrl); }); + icon->setMouseUpCallback([this](LLUICtrl* ctrl, S32, S32, MASK mask) { onEmojiMouseClick(ctrl, mask); }); + icon->setBackgroundColor(bgcolors[iconIndex % bgcolorCount]); + icon->setBackgroundOpaque(1); + icon->setRect(icon_rect); + row->mList->addPanel(icon, true); + + iconIndex++; + } + } + }; + + const std::vector<LLEmojiGroup>& groups = LLEmojiDictionary::instance().getGroups(); + const LLEmojiDictionary::cat2descrs_map_t& category2Descr = LLEmojiDictionary::instance().getCategory2Descrs(); + if (!sSelectedGroupIndex) + { + // List all groups + for (const LLEmojiGroup& group : groups) + { + // List all categories in group + for (const std::string& category : group.Categories) + { + // List all emojis in category + const LLEmojiDictionary::cat2descrs_map_t::const_iterator& item = category2Descr.find(category); + if (item != category2Descr.end()) + { + listCategory(category, item->second); + } + } + } + } + else + { + // List all categories in the selected group + for (const std::string& category : groups[sSelectedGroupIndex].Categories) + { + // List all emojis in category + const LLEmojiDictionary::cat2descrs_map_t::const_iterator& item = category2Descr.find(category); + if (item != category2Descr.end()) + { + listCategory(category, item->second); + } + } + } } bool LLFloaterEmojiPicker::matchesPattern(const LLEmojiDescriptor* descr) { - if (descr->Name.find(mSearchPattern) != std::string::npos) - return true; - for (const std::string& shortCode : descr->ShortCodes) - if (shortCode.find(mSearchPattern) != std::string::npos) - return true; - return false; + for (const std::string& shortCode : descr->ShortCodes) + if (shortCode.find(sSearchPattern) != std::string::npos) + return true; + return false; } -void LLFloaterEmojiPicker::onCategoryCommit() +void LLFloaterEmojiPicker::onGroupButtonClick(LLUICtrl* ctrl) { - mSelectedCategory = mCategory->getSelectedValue().asString(); - mRecentMaxIcons = 0; - fillEmojiGrid(); + if (LLButton* button = dynamic_cast<LLButton*>(ctrl)) + { + if (button == mGroupButtons[sSelectedGroupIndex] || button->getToggleState()) + return; + + auto it = std::find(mGroupButtons.begin(), mGroupButtons.end(), button); + if (it == mGroupButtons.end()) + return; + + mGroupButtons[sSelectedGroupIndex]->setToggleState(FALSE); + sSelectedGroupIndex = it - mGroupButtons.begin(); + mGroupButtons[sSelectedGroupIndex]->setToggleState(TRUE); + + LLRect rect = mBadge->getRect(); + rect.mLeft = button->getRect().mLeft; + rect.mRight = button->getRect().mRight; + mBadge->setRect(rect); + + mSearch->setFocus(TRUE); + + fillEmojis(); + } } void LLFloaterEmojiPicker::onSearchKeystroke() { - mSearchPattern = mSearch->getText(); - mRecentMaxIcons = 0; - fillEmojiGrid(); + sSearchPattern = mSearch->getText(); + fillEmojis(); } void LLFloaterEmojiPicker::onPreviewEmojiClick() { - if (mEmojiPickCallback) - { - if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(mHoveredIcon)) - { - mEmojiPickCallback(icon->getEmoji()); - } - } + if (mEmojiPickCallback) + { + if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(mHoveredIcon)) + { + mEmojiPickCallback(icon->getEmoji()); + } + } } void LLFloaterEmojiPicker::onGridMouseEnter() { - mSearch->setVisible(FALSE); - mDescription->setText(LLStringExplicit(""), LLStyle::Params()); - mDescription->setVisible(TRUE); + mSearch->setVisible(FALSE); + mDescription->setText(LLStringExplicit(""), LLStyle::Params()); + mDescription->setVisible(TRUE); } void LLFloaterEmojiPicker::onGridMouseLeave() { - mDescription->setVisible(FALSE); - mDescription->setText(LLStringExplicit(""), LLStyle::Params()); - mSearch->setVisible(TRUE); - mSearch->setFocus(TRUE); + mDescription->setVisible(FALSE); + mDescription->setText(LLStringExplicit(""), LLStyle::Params()); + mSearch->setVisible(TRUE); + mSearch->setFocus(TRUE); +} + +void LLFloaterEmojiPicker::onGroupButtonMouseEnter(LLUICtrl* ctrl) +{ + if (LLButton* button = dynamic_cast<LLButton*>(ctrl)) + { + button->setUseFontColor(TRUE); + } +} + +void LLFloaterEmojiPicker::onGroupButtonMouseLeave(LLUICtrl* ctrl) +{ + if (LLButton* button = dynamic_cast<LLButton*>(ctrl)) + { + button->setUseFontColor(FALSE); + } } void LLFloaterEmojiPicker::onEmojiMouseEnter(LLUICtrl* ctrl) { - if (ctrl) - { - if (mHoveredIcon && mHoveredIcon != ctrl) - { - unselectGridIcon(mHoveredIcon); - } + if (ctrl) + { + if (mHoveredIcon && mHoveredIcon != ctrl) + { + unselectGridIcon(mHoveredIcon); + } - selectGridIcon(ctrl); + selectGridIcon(ctrl); - mHoveredIcon = ctrl; - } + mHoveredIcon = ctrl; + } } void LLFloaterEmojiPicker::onEmojiMouseLeave(LLUICtrl* ctrl) { - if (ctrl) - { - if (ctrl == mHoveredIcon) - { - unselectGridIcon(ctrl); - } - } + if (ctrl) + { + if (ctrl == mHoveredIcon) + { + unselectGridIcon(ctrl); + } + } } void LLFloaterEmojiPicker::onEmojiMouseClick(LLUICtrl* ctrl, MASK mask) { - if (mEmojiPickCallback) - { - if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) - { - mPreviewEmoji->handleAnyMouseClick(0, 0, 0, EMouseClickType::CLICK_LEFT, TRUE); - mPreviewEmoji->handleAnyMouseClick(0, 0, 0, EMouseClickType::CLICK_LEFT, FALSE); - if (!(mask & 4)) - { - closeFloater(); - } - } - } + if (mEmojiPickCallback) + { + if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) + { + mPreviewEmoji->handleAnyMouseClick(0, 0, 0, EMouseClickType::CLICK_LEFT, TRUE); + mPreviewEmoji->handleAnyMouseClick(0, 0, 0, EMouseClickType::CLICK_LEFT, FALSE); + if (!(mask & 4)) + { + closeFloater(); + } + } + } } void LLFloaterEmojiPicker::selectGridIcon(LLUICtrl* ctrl) { - if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) - { - icon->setBackgroundVisible(TRUE); + if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) + { + icon->setBackgroundVisible(TRUE); - LLUIString text; - text.insert(0, icon->getText()); - mPreviewEmoji->setLabel(text); + LLUIString text; + text.insert(0, icon->getText()); + mPreviewEmoji->setLabel(text); - std::string descr = icon->getDescr() + "\n" + icon->getCategory(); - mDescription->setText(LLStringExplicit(descr), LLStyle::Params()); - } + std::string descr = icon->getDescr() + "\n" + icon->getCategory(); + mDescription->setText(LLStringExplicit(descr), LLStyle::Params()); + } } void LLFloaterEmojiPicker::unselectGridIcon(LLUICtrl* ctrl) { - if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) - { - icon->setBackgroundVisible(FALSE); - mPreviewEmoji->setLabel(LLUIString()); - mDescription->setText(LLStringExplicit(""), LLStyle::Params()); - } + if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) + { + icon->setBackgroundVisible(FALSE); + mPreviewEmoji->setLabel(LLUIString()); + mDescription->setText(LLStringExplicit(""), LLStyle::Params()); + } } // virtual BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask) { - if (mask == MASK_NONE) - { - switch (key) - { - case KEY_ESCAPE: - closeFloater(); - return TRUE; - } - } - - return LLFloater::handleKeyHere(key, mask); + if (mask == MASK_NONE) + { + switch (key) + { + case KEY_ESCAPE: + closeFloater(); + return TRUE; + } + } + + return LLFloater::handleKeyHere(key, mask); } // virtual void LLFloaterEmojiPicker::closeFloater(bool app_quitting) { - LLFloater::closeFloater(app_quitting); - if (mFloaterCloseCallback) - { - mFloaterCloseCallback(); - } + LLFloater::closeFloater(app_quitting); + if (mFloaterCloseCallback) + { + mFloaterCloseCallback(); + } } diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h index 300d9a4d4a..7fa6ea46b0 100644 --- a/indra/newview/llfloateremojipicker.h +++ b/indra/newview/llfloateremojipicker.h @@ -33,62 +33,70 @@ struct LLEmojiDescriptor; class LLFloaterEmojiPicker : public LLFloater { - using super = LLFloater; + using super = LLFloater; public: - // The callback function will be called with an emoji char. - typedef boost::function<void (llwchar)> pick_callback_t; - typedef boost::function<void ()> close_callback_t; + // The callback function will be called with an emoji char. + typedef boost::function<void (llwchar)> pick_callback_t; + typedef boost::function<void ()> close_callback_t; - // Call this to select an emoji. - static LLFloaterEmojiPicker* getInstance(); - static LLFloaterEmojiPicker* showInstance(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr); + // Call this to select an emoji. + static LLFloaterEmojiPicker* getInstance(); + static LLFloaterEmojiPicker* showInstance(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr); - LLFloaterEmojiPicker(const LLSD& key); - virtual ~LLFloaterEmojiPicker(); + LLFloaterEmojiPicker(const LLSD& key); + virtual ~LLFloaterEmojiPicker(); - virtual BOOL postBuild() override; - virtual void dirtyRect() override; + virtual BOOL postBuild() override; + virtual void dirtyRect() override; - void show(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr); + void show(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr); - virtual void closeFloater(bool app_quitting = false) override; + virtual void closeFloater(bool app_quitting = false) override; private: - void fillEmojiGrid(); - - bool matchesPattern(const LLEmojiDescriptor* descr); - - void onCategoryCommit(); - void onSearchKeystroke(); - void onPreviewEmojiClick(); - void onGridMouseEnter(); - void onGridMouseLeave(); - void onEmojiMouseEnter(LLUICtrl* ctrl); - void onEmojiMouseLeave(LLUICtrl* ctrl); - void onEmojiMouseClick(LLUICtrl* ctrl, MASK mask); - - void selectGridIcon(LLUICtrl* ctrl); - void unselectGridIcon(LLUICtrl* ctrl); - - virtual BOOL handleKeyHere(KEY key, MASK mask) override; - - class LLComboBox* mCategory { nullptr }; - class LLLineEditor* mSearch { nullptr }; - class LLScrollContainer* mEmojiScroll { nullptr }; - class LLScrollingPanelList* mEmojiGrid { nullptr }; - class LLButton* mPreviewEmoji { nullptr }; - class LLTextBox* mDescription { nullptr }; - - pick_callback_t mEmojiPickCallback; - close_callback_t mFloaterCloseCallback; - - S32 mRecentGridWidth { 0 }; - S32 mRecentMaxIcons { 0 }; - LLUICtrl* mHoveredIcon { nullptr }; - - static std::string mSelectedCategory; - static std::string mSearchPattern; + void fillGroups(); + void moveGroups(); + void fillEmojis(bool fromResize = false); + + bool matchesPattern(const LLEmojiDescriptor* descr); + + void onGroupButtonClick(LLUICtrl* ctrl); + void onSearchKeystroke(); + void onPreviewEmojiClick(); + void onGridMouseEnter(); + void onGridMouseLeave(); + void onGroupButtonMouseEnter(LLUICtrl* ctrl); + void onGroupButtonMouseLeave(LLUICtrl* ctrl); + void onEmojiMouseEnter(LLUICtrl* ctrl); + void onEmojiMouseLeave(LLUICtrl* ctrl); + void onEmojiMouseClick(LLUICtrl* ctrl, MASK mask); + + void selectGridIcon(LLUICtrl* ctrl); + void unselectGridIcon(LLUICtrl* ctrl); + + virtual BOOL handleKeyHere(KEY key, MASK mask) override; + + class LLPanel* mGroups { nullptr }; + class LLPanel* mBadge { nullptr }; + class LLLineEditor* mSearch { nullptr }; + class LLScrollContainer* mEmojiScroll { nullptr }; + class LLScrollingPanelList* mEmojiGrid { nullptr }; + class LLButton* mPreviewEmoji { nullptr }; + class LLTextBox* mDescription { nullptr }; + + pick_callback_t mEmojiPickCallback; + close_callback_t mFloaterCloseCallback; + + std::vector<class LLButton*> mGroupButtons; + + S32 mRecentBadgeWidth { 0 }; + S32 mRecentGridWidth { 0 }; + S32 mRecentMaxIcons { 0 }; + LLUICtrl* mHoveredIcon { nullptr }; + + static size_t sSelectedGroupIndex; + static std::string sSearchPattern; }; #endif diff --git a/indra/newview/skins/default/xui/da/emoji_categories.xml b/indra/newview/skins/default/xui/da/emoji_categories.xml new file mode 100644 index 0000000000..456b18e4e2 --- /dev/null +++ b/indra/newview/skins/default/xui/da/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>smileys and følelser</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>mennesker and krop</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>komponenter</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>dyr and natur</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>mad and drikke</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>rejser and steder</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>oplevelser</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>objekter</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>symboler</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/de/emoji_categories.xml b/indra/newview/skins/default/xui/de/emoji_categories.xml new file mode 100644 index 0000000000..ed63d0bac9 --- /dev/null +++ b/indra/newview/skins/default/xui/de/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>Smileys and Emotionen</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>Menschen and Körper</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>Komponenten</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>Tiere and Natur</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>Essen and Trinken</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>Reisen and Orte</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>Aktivitäten</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>Gegenstände</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>Symbole</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/en/emoji_categories.xml b/indra/newview/skins/default/xui/en/emoji_categories.xml new file mode 100644 index 0000000000..0315d0c43a --- /dev/null +++ b/indra/newview/skins/default/xui/en/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>smileys and emotion</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>people and body</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>components</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>animals and nature</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>food and drink</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>travel and places</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>activities</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>objects</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>symbols</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml index 2e153933c0..2a534b23b9 100644 --- a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -7,8 +7,9 @@ legacy_header_height="0" can_resize="true" layout="topleft" + min_width="250" height="400" - width="200"> + width="250"> <line_editor name="Search" label="Type to search" @@ -19,7 +20,7 @@ bottom="14" left="34" height="29" - width="162" /> + width="212" /> <text name="Description" layout="bottomleft" @@ -28,7 +29,7 @@ bottom="14" left="42" height="29" - width="150" /> + width="200" /> <button name="PreviewEmoji" layout="bottomleft" @@ -46,7 +47,7 @@ top="25" left="0" height="330" - width="200"> + width="250"> <scrolling_panel_list name="EmojiGrid" layout="topleft" @@ -55,16 +56,26 @@ spacing="0" top="0" left="0" - width="200"/> + width="250"/> </scroll_container> - <combo_box - name="Category" - label="Choose a category" + <panel + name="Groups" layout="topleft" follows="top|left|right" - allow_text_entry="true" top="0" - left="2" + left="0" height="25" - width="196" /> + width="250"> + <panel + name="Badge" + layout="bottomleft" + follows="bottom|left" + background_visible="true" + background_opaque="true" + bg_opaque_color="FrogGreen" + bottom="0" + height="2" + width="20" + /> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/es/emoji_categories.xml b/indra/newview/skins/default/xui/es/emoji_categories.xml new file mode 100644 index 0000000000..b1b73eba5e --- /dev/null +++ b/indra/newview/skins/default/xui/es/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>emoticonos y emoción</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>personas y cuerpo</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>componentes</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>animales y la naturaleza</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>comida y bebida</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>viajes y lugares</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>actividades</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>objetos</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>símbolos</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/fr/emoji_categories.xml b/indra/newview/skins/default/xui/fr/emoji_categories.xml new file mode 100644 index 0000000000..38dc9cb8f8 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>smileys et émotion</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>les gens et le corps</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>composants</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>animaux et la nature</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>nourriture et boissons</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>voyages et lieux</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>activités</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>objets</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>symboles</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/it/emoji_categories.xml b/indra/newview/skins/default/xui/it/emoji_categories.xml new file mode 100644 index 0000000000..a4782e60a6 --- /dev/null +++ b/indra/newview/skins/default/xui/it/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>smileys and emozione</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>persone e corpo</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>componenti</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>animali and natura</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>cibo e bevande</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>viaggi and luoghi</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>attività</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>oggetti</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>simboli</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/ja/emoji_categories.xml b/indra/newview/skins/default/xui/ja/emoji_categories.xml new file mode 100644 index 0000000000..7750f4ad2e --- /dev/null +++ b/indra/newview/skins/default/xui/ja/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>スマイリーと感情</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>人体</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>コンポーネント</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>動物自然</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>飲み物・食べ物</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>旅行・場所</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>有効化</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>オブジェクト</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>シンボル</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/pl/emoji_categories.xml b/indra/newview/skins/default/xui/pl/emoji_categories.xml new file mode 100644 index 0000000000..9aad7af794 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>buźki and emocje</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>ludzie and ciało</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>składniki</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>zwierzęta and przyroda</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>jedzenie i picie</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>podróże and miejsca</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>aktywność</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>objekt</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>symbole</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/pt/emoji_categories.xml b/indra/newview/skins/default/xui/pt/emoji_categories.xml new file mode 100644 index 0000000000..887444b957 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>sorrisos e emoção</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>pessoas e corpo</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>componentes</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>animais e natureza</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>comida e bebida</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>viagens e lugares</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>atividades</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>objetos</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>símbolos</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/ru/emoji_categories.xml b/indra/newview/skins/default/xui/ru/emoji_categories.xml new file mode 100644 index 0000000000..b08f0d8117 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>смайлики и люди</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>тело людей</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>компонент</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>животные и природа</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>еда и напитки</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>путешествия и местности</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>варианты досуга</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>предметы</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>символы</string> + </map> + </array> +</llsd> diff --git a/indra/newview/skins/default/xui/zh/emoji_categories.xml b/indra/newview/skins/default/xui/zh/emoji_categories.xml new file mode 100644 index 0000000000..fbe6165eeb --- /dev/null +++ b/indra/newview/skins/default/xui/zh/emoji_categories.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" ?> +<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <array> + <map> + <key>Name</key> + <string>smileys and emotion</string> + <key>Category</key> + <string>笑脸</string> + </map> + <map> + <key>Name</key> + <string>people and body</string> + <key>Category</key> + <string>人体</string> + </map> + <map> + <key>Name</key> + <string>components</string> + <key>Category</key> + <string>组件</string> + </map> + <map> + <key>Name</key> + <string>animals and nature</string> + <key>Category</key> + <string>野生动物</string> + </map> + <map> + <key>Name</key> + <string>food and drink</string> + <key>Category</key> + <string>食物飲料</string> + </map> + <map> + <key>Name</key> + <string>travel and places</string> + <key>Category</key> + <string>旅遊地點</string> + </map> + <map> + <key>Name</key> + <string>activities</string> + <key>Category</key> + <string>个人活动</string> + </map> + <map> + <key>Name</key> + <string>objects</string> + <key>Category</key> + <string>物件</string> + </map> + <map> + <key>Name</key> + <string>symbols</string> + <key>Category</key> + <string>人的符号</string> + </map> + </array> +</llsd> |