Skip to content
Snippets Groups Projects
Commit dad25bcb authored by Kitty Barnett's avatar Kitty Barnett
Browse files

Add the emoji helper class which can be used by text-input controls to provide emoji picker support

parent ec23b4bc
No related branches found
No related tags found
No related merge requests found
......@@ -54,6 +54,7 @@ set(llui_SOURCE_FILES
lldraghandle.cpp
lleditmenuhandler.cpp
llemojidictionary.cpp
llemojihelper.cpp
llf32uictrl.cpp
llfiltereditor.cpp
llflashtimer.cpp
......@@ -165,6 +166,7 @@ set(llui_HEADER_FILES
lldockcontrol.h
lleditmenuhandler.h
llemojidictionary.h
llemojihelper.h
llf32uictrl.h
llfiltereditor.h
llflashtimer.h
......
/**
* @file llemojihelper.h
* @brief Header file for LLEmojiHelper
*
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llemojidictionary.h"
#include "llemojihelper.h"
#include "llfloater.h"
#include "llfloaterreg.h"
#include "lluictrl.h"
// ============================================================================
// Constants
//
constexpr char DEFAULT_EMOJI_HELPER_FLOATER[] = "emoji_complete";
constexpr S32 HELPER_FLOATER_OFFSET_X = 20;
constexpr S32 HELPER_FLOATER_OFFSET_Y = 0;
// ============================================================================
// LLEmojiHelper
//
std::string LLEmojiHelper::getToolTip(llwchar ch) const
{
return LLEmojiDictionary::instance().getNameFromEmoji(ch);
}
bool LLEmojiHelper::isActive(const LLUICtrl* ctrl_p) const
{
return mHostHandle.get() == ctrl_p;
}
// static
bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S32* pShortCodePos)
{
S32 shortCodePos = cursorPos;
while (shortCodePos > 1 &&
(LLStringOps::isAlnum(wtext[shortCodePos - 1]) || wtext[shortCodePos - 1] == L'-' || wtext[shortCodePos - 1] == L'_') )
{
shortCodePos--;
}
bool isShortCode = (L':' == wtext[shortCodePos - 1]) && (cursorPos - shortCodePos >= 2);
if (pShortCodePos)
*pShortCodePos = (isShortCode) ? shortCodePos - 1 : -1;
return isShortCode;
}
void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(LLWString)> cb)
{
if (mHelperHandle.isDead())
{
LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER);
mHelperHandle = pHelperFloater->getHandle();
mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())); }, std::placeholders::_2));
}
setHostCtrl(hostctrl_p);
mEmojiCommitCb = cb;
S32 floater_x, floater_y;
if (!hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView))
{
LL_ERRS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL;
return;
}
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);
pHelperFloater->openFloater(LLSD().with("hint", short_code));
}
void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p)
{
setHostCtrl(nullptr);
}
bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask)
{
if (mHelperHandle.isDead() || !isActive(ctrl_p))
{
return false;
}
return mHelperHandle.get()->handleKey(key, mask, true);
}
void LLEmojiHelper::onCommitEmoji(const LLWString& wstr)
{
if (!mHostHandle.isDead() && mEmojiCommitCb)
{
mEmojiCommitCb(wstr);
}
}
void LLEmojiHelper::setHostCtrl(LLUICtrl* hostctrl_p)
{
const LLUICtrl* pCurHostCtrl = mHostHandle.get();
if (pCurHostCtrl != hostctrl_p)
{
mHostCtrlFocusLostConn.disconnect();
mHostHandle.markDead();
mEmojiCommitCb = {};
if (!mHelperHandle.isDead())
{
mHelperHandle.get()->closeFloater();
}
if (hostctrl_p)
{
mHostHandle = hostctrl_p->getHandle();
mHostCtrlFocusLostConn = hostctrl_p->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); }));
}
}
}
/**
* @file llemojihelper.h
* @brief Header file for LLEmojiHelper
*
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#pragma once
#include "llhandle.h"
#include "llsingleton.h"
#include <boost/signals2.hpp>
class LLFloater;
class LLUICtrl;
class LLEmojiHelper : public LLSingleton<LLEmojiHelper>
{
LLSINGLETON(LLEmojiHelper) {}
~LLEmojiHelper() override {}
public:
// General
std::string getToolTip(llwchar ch) const;
bool isActive(const LLUICtrl* ctrl_p) const;
static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr);
void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(LLWString)> commit_cb);
void hideHelper(const LLUICtrl* ctrl_p);
// Eventing
bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask);
void onCommitEmoji(const LLWString& wstr);
protected:
LLUICtrl* getHostCtrl() const { return mHostHandle.get(); }
void setHostCtrl(LLUICtrl* hostctrl_p);
private:
LLHandle<LLUICtrl> mHostHandle;
LLHandle<LLFloater> mHelperHandle;
boost::signals2::connection mHostCtrlFocusLostConn;
boost::signals2::connection mHelperCommitConn;
std::function<void(LLWString)> mEmojiCommitCb;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment