Merge branch 'DRTVWR-489' of https://github.com/secondlife/viewer
# Conflicts: # autobuild.xml # indra/llcommon/CMakeLists.txt # indra/llui/llscrolllistctrl.h # indra/newview/CMakeLists.txt # indra/newview/llviewerfloaterreg.cpp # indra/newview/skins/default/textures/textures.xmlmaster
commit
719a2d31dc
|
|
@ -57,6 +57,7 @@ indra/newview/teleport_history.txt
|
|||
indra/newview/typed_locations.txt
|
||||
indra/newview/vivox-runtime
|
||||
indra/newview/skins/default/html/common/equirectangular/js
|
||||
emoji_characters.xml
|
||||
indra/server-linux-*
|
||||
indra/temp
|
||||
indra/test/linden_file.dat
|
||||
|
|
|
|||
|
|
@ -672,9 +672,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7b4aceaed511d44c4d1354b2162b59c7</string>
|
||||
<string>878eaf654926e400d67680100cb780c9</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107398/936936/bugsplat-1.0.7.576560-darwin64-576560.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113512/981912/bugsplat-1.0.7.579546-darwin64-579546.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -684,9 +684,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>53918c7c74b943cdc0bb90caf9657a84</string>
|
||||
<string>5b32c47ae8e8cf0d4106f08e8db18044</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107400/936949/bugsplat-4.0.3.0.576560-windows-576560.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113878/983697/bugsplat-4.0.3.0.579696-windows-579696.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -696,16 +696,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>19d6a55db101f02e7eb531daf3e8cfd1</string>
|
||||
<string>79c005fd8a660f8551b3c9ede64fa4ef</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107401/936948/bugsplat-.576560-windows64-576560.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113879/983696/bugsplat-4.0.3.0.579696-windows64-579696.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>4.0.3.0.576560</string>
|
||||
<string>4.0.3.0.579696</string>
|
||||
</map>
|
||||
<key>colladadom</key>
|
||||
<map>
|
||||
|
|
@ -999,6 +999,62 @@
|
|||
<key>version</key>
|
||||
<string>1.12.4.202209142021_91.1.21_g9dd45fe_chromium-91.0.4472.114</string>
|
||||
</map>
|
||||
<key>emoji_shortcodes</key>
|
||||
<map>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://github.com/secondlife/3p-emoji-shortcodes</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2017-2019 Miles Johnson.</string>
|
||||
<key>description</key>
|
||||
<string>Emoji shortcodes</string>
|
||||
<key>license</key>
|
||||
<string>MIT</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/emojibase-license.txt</string>
|
||||
<key>name</key>
|
||||
<string>emoji_shortcodes</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>darwin64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7ac35da9b1b5c9a05954edeef3fe8e54</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113242/980233/emoji_shortcodes-6.1.0.579438-darwin64-579438.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>3c5c4c7e3bb2eeef61e605b6690a63f3</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113244/980245/emoji_shortcodes-6.1.0.579438-windows-579438.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>087ce7e6d93dcd88b477b10d8e1ab259</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113243/980244/emoji_shortcodes-6.1.0.579438-windows64-579438.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>6.1.0.579438</string>
|
||||
</map>
|
||||
<key>expat</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
@ -3304,7 +3360,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>viewer-fonts</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright various</string>
|
||||
<string>Copyright 2016-2022 Brad Erickson CC-BY-4.0/MIT, Copyright 2016-2022 Twitter, Inc. CC-BY-4.0, Copyright 2013 Joe Loughry and Terence Eden MIT</string>
|
||||
<key>description</key>
|
||||
<string>Viewer fonts</string>
|
||||
<key>license</key>
|
||||
|
|
@ -3320,9 +3376,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>d47e0ed35dad11f0a5dc821758e2ae46</string>
|
||||
<string>6041bbd4001e3951f96ac3456c7906da</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109658/953998/viewer_fonts-1.577782-darwin64-577782.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113314/980656/viewer_fonts-1.579464-darwin64-579464.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3332,9 +3388,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7dc39bb7cd8133d251eaff9c9e16bdfd</string>
|
||||
<string>19c48abc168a1c4e0f0ec6d471b2e1bd</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109660/954010/viewer_fonts-1.577782-windows-577782.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113308/980632/viewer_fonts-1.579464-windows-579464.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3344,16 +3400,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>86134368c16c7d685156403e15a7cbcd</string>
|
||||
<string>1745ba6eec0108250446fe01d4aa065c</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109659/954009/viewer_fonts-1.577782-windows64-577782.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/113307/980631/viewer_fonts-1.579464-windows64-579464.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.577782</string>
|
||||
<string>1.579464</string>
|
||||
</map>
|
||||
<key>viewer-manager</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ Ansariel Hiller
|
|||
SL-15227
|
||||
SL-15398
|
||||
SL-18432
|
||||
SL-19623
|
||||
Aralara Rajal
|
||||
Arare Chantilly
|
||||
CHUIBUG-191
|
||||
|
|
@ -891,6 +892,7 @@ Kitty Barnett
|
|||
STORM-2149
|
||||
MAINT-7581
|
||||
MAINT-7081
|
||||
DRTVWR-489 (Internal JIRA that tracks Kitty's sizeable, epic contribution: support for Emoji characters in the Viewer [April 2023])
|
||||
Kolor Fall
|
||||
Komiko Okamoto
|
||||
Korvel Noh
|
||||
|
|
|
|||
|
|
@ -20,3 +20,4 @@ endif()
|
|||
use_prebuilt_binary(slvoice)
|
||||
use_prebuilt_binary(nanosvg)
|
||||
use_prebuilt_binary(viewer-fonts)
|
||||
use_prebuilt_binary(emoji_shortcodes)
|
||||
|
|
|
|||
|
|
@ -303,7 +303,6 @@ endif(NOT WORD_SIZE EQUAL 32)
|
|||
|
||||
target_link_libraries(
|
||||
llcommon
|
||||
ll::icu4c
|
||||
ll::apr
|
||||
ll::expat
|
||||
ll::jsoncpp
|
||||
|
|
@ -312,6 +311,7 @@ target_link_libraries(
|
|||
ll::uriparser
|
||||
ll::oslibraries
|
||||
ll::tracy
|
||||
ll::icu4c
|
||||
)
|
||||
|
||||
target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ public:
|
|||
static void replaceNonstandardASCII( string_type& string, T replacement );
|
||||
static void replaceChar( string_type& string, T target, T replacement );
|
||||
static void replaceString( string_type& string, string_type target, string_type replacement );
|
||||
static void capitalize(string_type& str);
|
||||
|
||||
static BOOL containsNonprintable(const string_type& string);
|
||||
static void stripNonprintable(string_type& string);
|
||||
|
|
@ -1609,6 +1610,20 @@ void LLStringUtilBase<T>::replaceTabsWithSpaces( string_type& str, size_type spa
|
|||
str = out_str;
|
||||
}
|
||||
|
||||
//static
|
||||
template<class T>
|
||||
void LLStringUtilBase<T>::capitalize(string_type& str)
|
||||
{
|
||||
if (str.size())
|
||||
{
|
||||
auto last = str[0] = toupper(str[0]);
|
||||
for (U32 i = 1; i < str.size(); ++i)
|
||||
{
|
||||
last = (last == ' ' || last == '-' || last == '_') ? str[i] = toupper(str[i]) : str[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
template<class T>
|
||||
BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& string)
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ LLButton::Params::Params()
|
|||
label_shadow("label_shadow", true),
|
||||
auto_resize("auto_resize", false),
|
||||
use_ellipses("use_ellipses", false),
|
||||
use_font_color("use_font_color", false),
|
||||
image_unselected("image_unselected"),
|
||||
image_selected("image_selected"),
|
||||
image_hover_selected("image_hover_selected"),
|
||||
|
|
@ -167,6 +168,7 @@ LLButton::LLButton(const LLButton::Params& p)
|
|||
mDropShadowedText(p.label_shadow),
|
||||
mAutoResize(p.auto_resize),
|
||||
mUseEllipses( p.use_ellipses ),
|
||||
mUseFontColor( p.use_font_color),
|
||||
mHAlign(p.font_halign),
|
||||
mLeftHPad(p.pad_left),
|
||||
mRightHPad(p.pad_right),
|
||||
|
|
@ -1026,7 +1028,7 @@ void LLButton::draw()
|
|||
LLFontGL::NORMAL,
|
||||
mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,
|
||||
S32_MAX, text_width,
|
||||
NULL, mUseEllipses);
|
||||
NULL, mUseEllipses, mUseFontColor);
|
||||
}
|
||||
|
||||
// <FS:Zi> Add checkbox control toggle
|
||||
|
|
@ -1095,6 +1097,16 @@ BOOL LLButton::toggleState()
|
|||
return flipped;
|
||||
}
|
||||
|
||||
void LLButton::setLabel( const std::string& label )
|
||||
{
|
||||
mUnselectedLabel = mSelectedLabel = label;
|
||||
}
|
||||
|
||||
void LLButton::setLabel( const LLUIString& label )
|
||||
{
|
||||
mUnselectedLabel = mSelectedLabel = label;
|
||||
}
|
||||
|
||||
void LLButton::setLabel( const LLStringExplicit& label )
|
||||
{
|
||||
setLabelUnselected(label);
|
||||
|
|
@ -1126,14 +1138,7 @@ bool LLButton::labelIsTruncated() const
|
|||
|
||||
const LLUIString& LLButton::getCurrentLabel() const
|
||||
{
|
||||
if( getToggleState() )
|
||||
{
|
||||
return mSelectedLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mUnselectedLabel;
|
||||
}
|
||||
return getToggleState() ? mSelectedLabel : mUnselectedLabel;
|
||||
}
|
||||
|
||||
void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ public:
|
|||
Optional<bool> label_shadow;
|
||||
Optional<bool> auto_resize;
|
||||
Optional<bool> use_ellipses;
|
||||
Optional<bool> use_font_color;
|
||||
|
||||
// images
|
||||
Optional<LLUIImage*> image_unselected,
|
||||
|
|
@ -178,6 +179,7 @@ public:
|
|||
void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; }
|
||||
void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; }
|
||||
void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
|
||||
void setUseFontColor( BOOL use_font_color) { mUseFontColor = use_font_color; }
|
||||
|
||||
|
||||
boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb);
|
||||
|
|
@ -248,6 +250,8 @@ public:
|
|||
|
||||
void autoResize(); // resize with label of current btn state
|
||||
void resize(LLUIString label); // resize with label input
|
||||
void setLabel(const std::string& label);
|
||||
void setLabel(const LLUIString& label);
|
||||
void setLabel( const LLStringExplicit& label);
|
||||
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
|
||||
void setLabelUnselected(const LLStringExplicit& label);
|
||||
|
|
@ -370,6 +374,7 @@ protected:
|
|||
bool mDropShadowedText;
|
||||
bool mAutoResize;
|
||||
bool mUseEllipses;
|
||||
bool mUseFontColor;
|
||||
bool mBorderEnabled;
|
||||
bool mFlashing;
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,12 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const
|
|||
return result;
|
||||
}
|
||||
|
||||
const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromEmoji(llwchar emoji) const
|
||||
{
|
||||
const auto it = mEmoji2Descr.find(emoji);
|
||||
return (mEmoji2Descr.end() != it) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromShortCode(const std::string& short_code) const
|
||||
{
|
||||
const auto it = mShortCode2Descr.find(short_code);
|
||||
|
|
@ -195,6 +201,10 @@ void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr)
|
|||
{
|
||||
mShortCode2Descr.insert(std::make_pair(shortCode, &mEmojis.back()));
|
||||
}
|
||||
for (const std::string& category : descr.Categories)
|
||||
{
|
||||
mCategory2Descrs[category].push_back(&mEmojis.back());
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -56,18 +56,28 @@ class LLEmojiDictionary : public LLParamSingleton<LLEmojiDictionary>, public LLI
|
|||
~LLEmojiDictionary() override {};
|
||||
|
||||
public:
|
||||
typedef std::map<llwchar, const LLEmojiDescriptor*> emoji2descr_map_t;
|
||||
typedef std::map<std::string, const LLEmojiDescriptor*> code2descr_map_t;
|
||||
typedef std::map<std::string, std::vector<const LLEmojiDescriptor*>> cat2descrs_map_t;
|
||||
|
||||
static void initClass();
|
||||
LLWString findMatchingEmojis(const std::string& needle) const;
|
||||
const LLEmojiDescriptor* getDescriptorFromEmoji(llwchar emoji) const;
|
||||
const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
|
||||
std::string getNameFromEmoji(llwchar ch) const;
|
||||
|
||||
const emoji2descr_map_t& getEmoji2Descr() const { return mEmoji2Descr; }
|
||||
const code2descr_map_t& getShortCode2Descr() const { return mShortCode2Descr; }
|
||||
const cat2descrs_map_t& getCategory2Descrs() const { return mCategory2Descrs; }
|
||||
|
||||
private:
|
||||
void addEmoji(LLEmojiDescriptor&& descr);
|
||||
|
||||
private:
|
||||
std::list<LLEmojiDescriptor> mEmojis;
|
||||
std::map<llwchar, const LLEmojiDescriptor*> mEmoji2Descr;
|
||||
std::map<std::string, const LLEmojiDescriptor*> mShortCode2Descr;
|
||||
emoji2descr_map_t mEmoji2Descr;
|
||||
code2descr_map_t mShortCode2Descr;
|
||||
cat2descrs_map_t mCategory2Descrs;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -82,12 +82,12 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S
|
|||
return isShortCode;
|
||||
}
|
||||
|
||||
void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(LLWString)> cb)
|
||||
void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(llwchar)> cb)
|
||||
{
|
||||
// Commit immediately if the user already typed a full shortcode
|
||||
if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code))
|
||||
{
|
||||
cb(LLWString(1, emojiDescrp->Character));
|
||||
cb(emojiDescrp->Character);
|
||||
hideHelper();
|
||||
return;
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c
|
|||
{
|
||||
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));
|
||||
mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2));
|
||||
}
|
||||
setHostCtrl(hostctrl_p);
|
||||
mEmojiCommitCb = cb;
|
||||
|
|
@ -135,11 +135,11 @@ bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask)
|
|||
return mHelperHandle.get()->handleKey(key, mask, true);
|
||||
}
|
||||
|
||||
void LLEmojiHelper::onCommitEmoji(const LLWString& wstr)
|
||||
void LLEmojiHelper::onCommitEmoji(llwchar emoji)
|
||||
{
|
||||
if (!mHostHandle.isDead() && mEmojiCommitCb)
|
||||
{
|
||||
mEmojiCommitCb(wstr);
|
||||
mEmojiCommitCb(emoji);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ public:
|
|||
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 showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(llwchar)> commit_cb);
|
||||
void hideHelper(const LLUICtrl* ctrl_p = nullptr);
|
||||
|
||||
// Eventing
|
||||
bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask);
|
||||
void onCommitEmoji(const LLWString& wstr);
|
||||
void onCommitEmoji(llwchar emoji);
|
||||
|
||||
protected:
|
||||
LLUICtrl* getHostCtrl() const { return mHostHandle.get(); }
|
||||
|
|
@ -60,5 +60,5 @@ private:
|
|||
LLHandle<LLFloater> mHelperHandle;
|
||||
boost::signals2::connection mHostCtrlFocusLostConn;
|
||||
boost::signals2::connection mHelperCommitConn;
|
||||
std::function<void(LLWString)> mEmojiCommitCb;
|
||||
std::function<void(llwchar)> mEmojiCommitCb;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1597,14 +1597,24 @@ BOOL LLFloater::isFrontmost()
|
|||
&& floater_view->getFrontmost() == this);
|
||||
}
|
||||
|
||||
void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition)
|
||||
void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition, BOOL resize)
|
||||
{
|
||||
mDependents.insert(floaterp->getHandle());
|
||||
floaterp->mDependeeHandle = getHandle();
|
||||
|
||||
if (reposition)
|
||||
{
|
||||
floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));
|
||||
LLRect rect = gFloaterView->findNeighboringPosition(this, floaterp);
|
||||
if (resize)
|
||||
{
|
||||
const LLRect& base = getRect();
|
||||
if (rect.mTop == base.mTop)
|
||||
rect.mBottom = base.mBottom;
|
||||
else if (rect.mLeft == base.mLeft)
|
||||
rect.mRight = base.mRight;
|
||||
floaterp->reshape(rect.getWidth(), rect.getHeight(), FALSE);
|
||||
}
|
||||
floaterp->setRect(rect);
|
||||
floaterp->setSnapTarget(getHandle());
|
||||
}
|
||||
gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE);
|
||||
|
|
@ -1615,12 +1625,12 @@ void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition)
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloater::addDependentFloater(LLHandle<LLFloater> dependent, BOOL reposition)
|
||||
void LLFloater::addDependentFloater(LLHandle<LLFloater> dependent, BOOL reposition, BOOL resize)
|
||||
{
|
||||
LLFloater* dependent_floaterp = dependent.get();
|
||||
if(dependent_floaterp)
|
||||
{
|
||||
addDependentFloater(dependent_floaterp, reposition);
|
||||
addDependentFloater(dependent_floaterp, reposition, resize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,8 +265,8 @@ public:
|
|||
std::string getShortTitle() const;
|
||||
virtual void setMinimized(BOOL b);
|
||||
void moveResizeHandlesToFront();
|
||||
void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE);
|
||||
void addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE);
|
||||
void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE, BOOL resize = FALSE);
|
||||
void addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE, BOOL resize = FALSE);
|
||||
LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); }
|
||||
void removeDependentFloater(LLFloater* dependent);
|
||||
BOOL isMinimized() const { return mMinimized; }
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ void LLScrollListCtrl::clearRows()
|
|||
LLScrollListItem* LLScrollListCtrl::getFirstSelected() const
|
||||
{
|
||||
item_list::const_iterator iter;
|
||||
for(iter = mItemList.begin(); iter != mItemList.end(); iter++)
|
||||
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
|
||||
{
|
||||
LLScrollListItem* item = *iter;
|
||||
if (item->getSelected())
|
||||
|
|
@ -1385,7 +1385,7 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen
|
|||
LLScrollListItem* item = getItemByLabel(label, case_sensitive, column);
|
||||
|
||||
bool found = NULL != item;
|
||||
if(found)
|
||||
if (found)
|
||||
{
|
||||
selectItem(item, -1);
|
||||
}
|
||||
|
|
@ -3161,7 +3161,7 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
|
|||
S32 LLScrollListCtrl::getLinesPerPage()
|
||||
{
|
||||
//if mPageLines is NOT provided display all item
|
||||
if(mPageLines)
|
||||
if (mPageLines)
|
||||
{
|
||||
return mPageLines;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ public:
|
|||
S32 getItemIndex( LLScrollListItem* item ) const;
|
||||
S32 getItemIndex( const LLUUID& item_id ) const;
|
||||
|
||||
void setCommentText( const std::string& comment_text);
|
||||
void setCommentText( const std::string& comment_text);
|
||||
// <FS:Ansariel> Allow appending of comment text
|
||||
void addCommentText( const std::string& comment_text);
|
||||
// </FS:Ansariel> Allow appending of comment text
|
||||
|
|
@ -277,7 +277,7 @@ public:
|
|||
BOOL selectItemBySubstring(const LLWString& target, BOOL case_sensitive = TRUE);
|
||||
BOOL selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive = TRUE, S32 column = -1);
|
||||
// </FS:Ansariel>
|
||||
LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );
|
||||
LLScrollListItem* getItemByLabel(const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0);
|
||||
const std::string getSelectedItemLabel(S32 column = 0) const;
|
||||
LLSD getSelectedValue();
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ public:
|
|||
|
||||
virtual S32 getScrollPos() const;
|
||||
virtual void setScrollPos( S32 pos );
|
||||
S32 getSearchColumn();
|
||||
S32 getSearchColumn();
|
||||
void setSearchColumn(S32 column) { mSearchColumn = column; }
|
||||
S32 getColumnIndexFromOffset(S32 x);
|
||||
S32 getColumnOffsetFromIndex(S32 index);
|
||||
|
|
@ -394,13 +394,13 @@ public:
|
|||
// Used "internally" by the scroll bar.
|
||||
void onScrollChange( S32 new_pos, LLScrollbar* src );
|
||||
|
||||
static void onClickColumn(void *userdata);
|
||||
static void onClickColumn(void *userdata);
|
||||
|
||||
virtual void updateColumns(bool force_update = false);
|
||||
S32 calcMaxContentWidth();
|
||||
bool updateColumnWidths();
|
||||
virtual void updateColumns(bool force_update = false);
|
||||
S32 calcMaxContentWidth();
|
||||
bool updateColumnWidths();
|
||||
|
||||
void setHeadingHeight(S32 heading_height);
|
||||
void setHeadingHeight(S32 heading_height);
|
||||
/**
|
||||
* Sets max visible lines without scroolbar, if this value equals to 0,
|
||||
* then display all items.
|
||||
|
|
@ -421,18 +421,20 @@ public:
|
|||
virtual void deselect();
|
||||
virtual BOOL canDeselect() const;
|
||||
|
||||
void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; }
|
||||
void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width);
|
||||
S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; }
|
||||
void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; }
|
||||
void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width);
|
||||
S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; }
|
||||
|
||||
std::string getSortColumnName();
|
||||
BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
|
||||
BOOL hasSortOrder() const;
|
||||
void clearSortOrder();
|
||||
|
||||
void setAlternateSort() { mAlternateSort = true; }
|
||||
void setAlternateSort() { mAlternateSort = TRUE; }
|
||||
|
||||
S32 selectMultiple( uuid_vec_t ids );
|
||||
void selectPrevItem(BOOL extend_selection = FALSE);
|
||||
void selectNextItem(BOOL extend_selection = FALSE);
|
||||
S32 selectMultiple(uuid_vec_t ids);
|
||||
// conceptually const, but mutates mItemList
|
||||
void updateSort() const;
|
||||
// sorts a list without affecting the permanent sort order (so further list insertions can be unsorted, for example)
|
||||
|
|
@ -487,8 +489,6 @@ public:
|
|||
mutable U32 mLastUpdateFrame;
|
||||
|
||||
private:
|
||||
void selectPrevItem(BOOL extend_selection);
|
||||
void selectNextItem(BOOL extend_selection);
|
||||
void drawItems();
|
||||
|
||||
void updateLineHeightInsert(LLScrollListItem* item);
|
||||
|
|
|
|||
|
|
@ -731,18 +731,24 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p
|
|||
endSelection();
|
||||
}
|
||||
|
||||
void LLTextEditor::handleEmojiCommit(const LLWString& wstr)
|
||||
void LLTextEditor::insertEmoji(llwchar emoji)
|
||||
{
|
||||
LLWString wtext(getWText()); S32 shortCodePos;
|
||||
if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos))
|
||||
auto styleParams = LLStyle::Params();
|
||||
styleParams.font = LLFontGL::getFontEmoji();
|
||||
auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this);
|
||||
insert(mCursorPos, LLWString(1, emoji), false, segment);
|
||||
setCursorPos(mCursorPos + 1);
|
||||
}
|
||||
|
||||
void LLTextEditor::handleEmojiCommit(llwchar emoji)
|
||||
{
|
||||
S32 shortCodePos;
|
||||
if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos))
|
||||
{
|
||||
remove(shortCodePos, mCursorPos - shortCodePos, true);
|
||||
setCursorPos(shortCodePos);
|
||||
|
||||
auto styleParams = LLStyle::Params();
|
||||
styleParams.font = LLFontGL::getFontEmoji();
|
||||
insert(shortCodePos, wstr, false, new LLEmojiTextSegment(new LLStyle(styleParams), shortCodePos, shortCodePos + wstr.size(), *this));
|
||||
|
||||
setCursorPos(shortCodePos + 1);
|
||||
insertEmoji(emoji);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ public:
|
|||
|
||||
static S32 spacesPerTab();
|
||||
|
||||
void handleEmojiCommit(const LLWString& wstr);
|
||||
void insertEmoji(llwchar emoji);
|
||||
void handleEmojiCommit(llwchar emoji);
|
||||
|
||||
// mousehandler overrides
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
|
|
|
|||
|
|
@ -315,6 +315,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloaterdisplayname.cpp
|
||||
llfloatereditenvironmentbase.cpp
|
||||
llfloatereditextdaycycle.cpp
|
||||
llfloateremojipicker.cpp
|
||||
llfloaterenvironmentadjust.cpp
|
||||
llfloaterevent.cpp
|
||||
llfloaterexperiencepicker.cpp
|
||||
|
|
@ -1097,6 +1098,7 @@ set(viewer_HEADER_FILES
|
|||
llfloaterdisplayname.h
|
||||
llfloatereditenvironmentbase.h
|
||||
llfloatereditextdaycycle.h
|
||||
llfloateremojipicker.h
|
||||
llfloaterenvironmentadjust.h
|
||||
llfloaterevent.h
|
||||
llfloaterexperiencepicker.h
|
||||
|
|
@ -2430,6 +2432,22 @@ set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
|
|||
#file(COPY ${FONT_FILE_GLOB_LIST} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/fonts")
|
||||
# </FS:Ansariel>
|
||||
|
||||
# Copy over the Emoji/shortcodes mapping XML files (and create dependency
|
||||
# if they are changed, CMake will run again and copy over new versions)
|
||||
message("Copying Emoji/shortcode mappings")
|
||||
set(emoji_mapping_src_folder ${AUTOBUILD_INSTALL_DIR}/xui)
|
||||
set(emoji_mapping_dst_folder ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui)
|
||||
|
||||
# Note Turkey is missing from this set (not available in Emoji package yet)
|
||||
set(country_codes "da;de;en;es;fr;it;ja;pl;pt;ru;zh")
|
||||
foreach(elem ${country_codes})
|
||||
set(emoji_mapping_src_file
|
||||
"${emoji_mapping_src_folder}/${elem}/emoji_characters.xml")
|
||||
set(emoji_mapping_dst_file
|
||||
"${emoji_mapping_dst_folder}/${elem}/emoji_characters.xml")
|
||||
configure_file(${emoji_mapping_src_file} ${emoji_mapping_dst_file} COPYONLY)
|
||||
endforeach()
|
||||
|
||||
if (LINUX)
|
||||
set(product Firestorm-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION})
|
||||
|
||||
|
|
|
|||
|
|
@ -930,7 +930,6 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&
|
|||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
|
||||
{
|
||||
getChildView("Find")->setEnabled(caller->getText().size() > 0);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,296 @@
|
|||
/**
|
||||
* @file llfloateremojipicker.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, 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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloateremojipicker.h"
|
||||
|
||||
#include "llcombobox.h"
|
||||
#include "llemojidictionary.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llscrolllistitem.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llviewerchat.h"
|
||||
|
||||
std::string LLFloaterEmojiPicker::mSelectedCategory;
|
||||
std::string LLFloaterEmojiPicker::mSearchPattern;
|
||||
int LLFloaterEmojiPicker::mSelectedEmojiIndex;
|
||||
|
||||
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);
|
||||
|
||||
S32 width = getColumn(0)->getWidth();
|
||||
LLFontGL::getFontEmoji()->render(LLWString(1, mEmoji), 0, rect.mLeft + width / 2, rect.getCenterY(), LLColor4::white,
|
||||
LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW_SOFT, 1, S32_MAX, nullptr, false, true);
|
||||
}
|
||||
|
||||
private:
|
||||
llwchar mEmoji;
|
||||
};
|
||||
|
||||
LLFloaterEmojiPicker* LLFloaterEmojiPicker::getInstance()
|
||||
{
|
||||
LLFloaterEmojiPicker* floater = LLFloaterReg::getTypedInstance<LLFloaterEmojiPicker>("emoji_picker");
|
||||
if (!floater)
|
||||
LL_WARNS() << "Cannot instantiate emoji picker" << LL_ENDL;
|
||||
return floater;
|
||||
}
|
||||
|
||||
LLFloaterEmojiPicker* LLFloaterEmojiPicker::showInstance(pick_callback_t pick_callback, close_callback_t close_callback)
|
||||
{
|
||||
LLFloaterEmojiPicker* floater = getInstance();
|
||||
if (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);
|
||||
}
|
||||
|
||||
LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key)
|
||||
: LLFloater(key)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLFloaterEmojiPicker::postBuild()
|
||||
{
|
||||
// Should be initialized first
|
||||
if ((mPreviewEmoji = getChild<LLButton>("PreviewEmoji")))
|
||||
{
|
||||
mPreviewEmoji->setClickedCallback(boost::bind(&LLFloaterEmojiPicker::onPreviewEmojiClick, this));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
LLFloaterEmojiPicker::~LLFloaterEmojiPicker()
|
||||
{
|
||||
gFocusMgr.releaseFocusIfNeeded( this );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
mSearchPattern = mSearch->getText();
|
||||
mSelectedEmojiIndex = 0;
|
||||
fillEmojis();
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::onPreviewEmojiClick()
|
||||
{
|
||||
if (mEmojis && mEmojiPickCallback)
|
||||
{
|
||||
if (LLEmojiScrollListItem* item = dynamic_cast<LLEmojiScrollListItem*>(mEmojis->getFirstSelected()))
|
||||
{
|
||||
mEmojiPickCallback(item->getEmoji());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::onEmojiSelect()
|
||||
{
|
||||
const LLEmojiScrollListItem* item = dynamic_cast<LLEmojiScrollListItem*>(mEmojis->getFirstSelected());
|
||||
if (item)
|
||||
{
|
||||
mSelectedEmojiIndex = mEmojis->getFirstSelectedIndex();
|
||||
LLUIString text;
|
||||
text.insert(0, LLWString(1, item->getEmoji()));
|
||||
if (mPreviewEmoji)
|
||||
mPreviewEmoji->setLabel(text);
|
||||
return;
|
||||
}
|
||||
|
||||
onEmojiEmpty();
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::onEmojiEmpty()
|
||||
{
|
||||
mSelectedEmojiIndex = 0;
|
||||
if (mPreviewEmoji)
|
||||
mPreviewEmoji->setLabel(LLUIString());
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::onEmojiPick()
|
||||
{
|
||||
if (mEmojis && mEmojiPickCallback)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* @file llfloateremojipicker.h
|
||||
* @brief Header file for llfloateremojipicker
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, 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$
|
||||
*/
|
||||
|
||||
#ifndef LLFLOATEREMOJIPICKER_H
|
||||
#define LLFLOATEREMOJIPICKER_H
|
||||
|
||||
#include "llfloater.h"
|
||||
|
||||
struct LLEmojiDescriptor;
|
||||
|
||||
class LLFloaterEmojiPicker : public 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;
|
||||
|
||||
// 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();
|
||||
|
||||
virtual BOOL postBuild();
|
||||
|
||||
void show(pick_callback_t pick_callback = nullptr, close_callback_t close_callback = nullptr);
|
||||
|
||||
virtual void closeFloater(bool app_quitting = false);
|
||||
|
||||
private:
|
||||
void fillEmojis();
|
||||
bool matchesCategory(const LLEmojiDescriptor* descr);
|
||||
bool matchesPattern(const LLEmojiDescriptor* descr);
|
||||
|
||||
void onCategoryCommit();
|
||||
void onSearchKeystroke(class LLLineEditor* caller, void* user_data);
|
||||
void onPreviewEmojiClick();
|
||||
void onEmojiSelect();
|
||||
void onEmojiEmpty();
|
||||
void onEmojiPick();
|
||||
|
||||
virtual BOOL handleKeyHere(KEY key, MASK mask);
|
||||
|
||||
class LLComboBox* mCategory { nullptr };
|
||||
class LLLineEditor* mSearch { nullptr };
|
||||
class LLScrollListCtrl* mEmojis { nullptr };
|
||||
class LLButton* mPreviewEmoji { nullptr };
|
||||
|
||||
pick_callback_t mEmojiPickCallback;
|
||||
close_callback_t mFloaterCloseCallback;
|
||||
|
||||
static std::string mSelectedCategory;
|
||||
static std::string mSearchPattern;
|
||||
static int mSelectedEmojiIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
#include "llchicletbar.h"
|
||||
#include "lldraghandle.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloateremojipicker.h"
|
||||
#include "llfloaterimsession.h"
|
||||
#include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container
|
||||
#include "lllayoutstack.h"
|
||||
|
|
@ -252,10 +253,13 @@ BOOL LLFloaterIMSessionTab::postBuild()
|
|||
mTearOffBtn = getChild<LLButton>("tear_off_btn");
|
||||
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
|
||||
|
||||
mEmojiBtn = getChild<LLButton>("emoji_panel_btn");
|
||||
mEmojiBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onEmojiPanelBtnClicked, this));
|
||||
|
||||
mGearBtn = getChild<LLButton>("gear_btn");
|
||||
mAddBtn = getChild<LLButton>("add_btn");
|
||||
mVoiceButton = getChild<LLButton>("voice_call_btn");
|
||||
|
||||
|
||||
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
|
||||
mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
|
||||
|
||||
|
|
@ -426,6 +430,37 @@ void LLFloaterIMSessionTab::onInputEditorClicked()
|
|||
gToolBarView->flashCommand(LLCommandId("chat"), false);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self)
|
||||
{
|
||||
if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance())
|
||||
{
|
||||
if (!picker->isShown())
|
||||
{
|
||||
picker->show(
|
||||
boost::bind(&LLFloaterIMSessionTab::onEmojiPicked, self, _1),
|
||||
boost::bind(&LLFloaterIMSessionTab::onEmojiPickerClosed, self));
|
||||
if (LLFloater* root_floater = gFloaterView->getParentFloater(self))
|
||||
{
|
||||
root_floater->addDependentFloater(picker, TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
picker->closeFloater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPicked(llwchar emoji)
|
||||
{
|
||||
mInputEditor->insertEmoji(emoji);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPickerClosed()
|
||||
{
|
||||
mInputEditor->setFocus(TRUE);
|
||||
}
|
||||
|
||||
std::string LLFloaterIMSessionTab::appendTime()
|
||||
{
|
||||
time_t utc_time;
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ protected:
|
|||
LLButton* mExpandCollapseLineBtn;
|
||||
LLButton* mExpandCollapseBtn;
|
||||
LLButton* mTearOffBtn;
|
||||
LLButton* mEmojiBtn;
|
||||
LLButton* mCloseBtn;
|
||||
LLButton* mGearBtn;
|
||||
LLButton* mAddBtn;
|
||||
|
|
@ -208,6 +209,10 @@ private:
|
|||
|
||||
void onInputEditorClicked();
|
||||
|
||||
static void onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self);
|
||||
void onEmojiPicked(llwchar emoji);
|
||||
void onEmojiPickerClosed();
|
||||
|
||||
bool checkIfTornOff();
|
||||
bool mIsHostAttached;
|
||||
bool mHasVisibleBeenInitialized;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llviewerchat.h"
|
||||
#include "llviewerchat.h"
|
||||
|
||||
// newview includes
|
||||
#include "llagent.h" // gAgent
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
#include "llfloaterdestinations.h"
|
||||
#include "llfloaterdisplayname.h"
|
||||
#include "llfloatereditextdaycycle.h"
|
||||
#include "llfloateremojipicker.h"
|
||||
#include "llfloaterenvironmentadjust.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
#include "llfloaterexperiences.h"
|
||||
|
|
@ -400,7 +401,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
//LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater);
|
||||
LLFloaterReg::add("fs_nearby_chat", "floater_fs_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterNearbyChat>);
|
||||
// </FS:Ansariel> [FS communication UI]
|
||||
LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>);
|
||||
LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>);
|
||||
LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
|
||||
LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);
|
||||
LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>);
|
||||
|
|
@ -408,19 +409,20 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeletePrefPreset>);
|
||||
LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
|
||||
|
||||
LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", &LLFloaterReg::build<LLFloaterEmojiComplete>);
|
||||
LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiPicker>);
|
||||
LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiComplete>);
|
||||
LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
|
||||
|
||||
LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
|
||||
LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>);
|
||||
LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
|
||||
LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>);
|
||||
|
||||
LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>);
|
||||
LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>);
|
||||
|
||||
LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>);
|
||||
LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>);
|
||||
LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>);
|
||||
LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>);
|
||||
|
||||
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
|
||||
LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
|
||||
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
|
||||
LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
|
||||
LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperienceProfile>);
|
||||
LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 316 B |
|
|
@ -222,6 +222,7 @@ with the same filename but different name
|
|||
|
||||
<texture name="DropTarget" file_name="widgets/DropTarget.png" preload="false" />
|
||||
|
||||
<texture name="Emoji_Picker_Icon" file_name="icons/emoji_picker_icon.png" preload="true" />
|
||||
<texture name="ExternalBrowser_Off" file_name="icons/ExternalBrowser_Off.png" preload="false" />
|
||||
<texture name="ExternalBrowser_Over" file_name="icons/ExternalBrowser_Over.png" preload="false" />
|
||||
<texture name="ExternalBrowser_Press" file_name="icons/ExternalBrowser_Press.png" preload="false" />
|
||||
|
|
@ -229,7 +230,6 @@ with the same filename but different name
|
|||
|
||||
<texture name="Presets_Icon" file_name="icons/Presets_Icon.png" preload="true" />
|
||||
<texture name="Presets_Icon_Graphic" file_name="icons/Presets_Icon_Graphic.png" preload="true" />
|
||||
|
||||
<texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />
|
||||
<texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />
|
||||
<texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater
|
||||
name="emojipicker"
|
||||
title="CHOOSE EMOJI"
|
||||
help_topic="emojipicker"
|
||||
positioning="cascading"
|
||||
legacy_header_height="0"
|
||||
can_resize="true"
|
||||
layout="topleft"
|
||||
height="400"
|
||||
width="200">
|
||||
<line_editor
|
||||
name="Search"
|
||||
layout="bottomleft"
|
||||
follows="bottom|left|right"
|
||||
text_tentative_color="TextFgTentativeColor"
|
||||
max_length_bytes="63"
|
||||
left_pad="5"
|
||||
bottom="14"
|
||||
left="34"
|
||||
height="29"
|
||||
width="162" />
|
||||
<button
|
||||
name="PreviewEmoji"
|
||||
layout="bottomleft"
|
||||
follows="bottom|left"
|
||||
font="EmojiHuge"
|
||||
use_font_color="true"
|
||||
bottom="14"
|
||||
left="0"
|
||||
height="29"
|
||||
width="29" />
|
||||
<scroll_list
|
||||
name="Emojis"
|
||||
layout="topleft"
|
||||
follows="all"
|
||||
sort_column="0"
|
||||
max_chars="63"
|
||||
commit_on_selection_change="true"
|
||||
draw_heading="true"
|
||||
heading_height="25"
|
||||
row_padding="0"
|
||||
top="25"
|
||||
height="330"
|
||||
width="200">
|
||||
<columns
|
||||
label="Look"
|
||||
name="look"
|
||||
width="40" />
|
||||
<columns
|
||||
label="Name"
|
||||
name="name" />
|
||||
</scroll_list>
|
||||
<combo_box
|
||||
name="Category"
|
||||
layout="topleft"
|
||||
follows="top|left|right"
|
||||
allow_text_entry="true"
|
||||
left_pad="4"
|
||||
top="0"
|
||||
left="4"
|
||||
height="27"
|
||||
width="192" />
|
||||
</floater>
|
||||
|
|
@ -297,8 +297,20 @@
|
|||
tab_group="3"
|
||||
bottom="-8"
|
||||
left_pad="5"
|
||||
right="-5"
|
||||
right="-30"
|
||||
wrap="true" />
|
||||
<button
|
||||
follows="right|bottom"
|
||||
bottom="-7"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="Emoji_Picker_Icon"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
right="-1"
|
||||
name="emoji_panel_btn"
|
||||
tool_tip="Shows/hides emoji panel"
|
||||
width="25"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
|
|
|
|||
|
|
@ -559,9 +559,9 @@ https://www.firestormviewer.org/support for help fixing this problem.
|
|||
<!-- build floater -->
|
||||
<string name="multiple_textures">Multiple</string>
|
||||
|
||||
<string name="use_texture">Use texture</string>
|
||||
<string name="manip_hint1">Move mouse cursor over ruler</string>
|
||||
<string name="manip_hint2">to snap to grid</string>
|
||||
<string name="use_texture">Use texture</string>
|
||||
<string name="manip_hint1">Move mouse cursor over ruler</string>
|
||||
<string name="manip_hint2">to snap to grid</string>
|
||||
|
||||
<!-- world map -->
|
||||
<string name="texture_loading">Loading...</string>
|
||||
|
|
@ -582,14 +582,14 @@ https://www.firestormviewer.org/support for help fixing this problem.
|
|||
<!-- Chat -->
|
||||
<string name="no_name_object">(no name)</string>
|
||||
<string name="NearbyChatTitle">Nearby chat</string>
|
||||
<string name="NearbyChatLabel">(Nearby chat)</string>
|
||||
<string name="NearbyChatLabel">(Nearby chat)</string>
|
||||
<string name="whisper">whispers:</string>
|
||||
<string name="shout">shouts:</string>
|
||||
<string name="ringing">Connecting to in-world Voice Chat...</string>
|
||||
<string name="connected">Connected</string>
|
||||
<string name="unavailable">Voice not available at your current location</string>
|
||||
<string name="hang_up">Disconnected from in-world Voice Chat</string>
|
||||
<string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string>
|
||||
<string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string>
|
||||
<string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string>
|
||||
<string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string>
|
||||
<string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue