SL-19575 Create emoji gallery access icon

master
Alexander Gavriliuk 2023-04-14 07:44:56 +02:00
parent 638a45cbb1
commit ff7ebf0892
17 changed files with 335 additions and 36 deletions

View File

@ -61,6 +61,8 @@ public:
const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
std::string getNameFromEmoji(llwchar ch) const;
const std::map<llwchar, const LLEmojiDescriptor*>& getEmoji2Descr() const { return mEmoji2Descr; }
private:
void addEmoji(LLEmojiDescriptor&& descr);

View File

@ -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);
}
}

View File

@ -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;
};

View File

@ -411,7 +411,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())

View File

@ -680,18 +680,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);
}
}

View File

@ -92,7 +92,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);

View File

@ -205,6 +205,7 @@ set(viewer_SOURCE_FILES
llfloaterdisplayname.cpp
llfloatereditenvironmentbase.cpp
llfloatereditextdaycycle.cpp
llfloateremojipicker.cpp
llfloaterenvironmentadjust.cpp
llfloaterevent.cpp
llfloaterexperiencepicker.cpp
@ -845,6 +846,7 @@ set(viewer_HEADER_FILES
llfloaterdisplayname.h
llfloatereditenvironmentbase.h
llfloatereditextdaycycle.h
llfloateremojipicker.h
llfloaterenvironmentadjust.h
llfloaterevent.h
llfloaterexperiencepicker.h

View File

@ -0,0 +1,143 @@
/**
* @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 "llfloaterreg.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llemojidictionary.h"
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(select_callback_t callback)
{
LLFloaterEmojiPicker* floater = getInstance();
if (LLFloaterEmojiPicker* floater = getInstance())
floater->show(callback);
return floater;
}
void LLFloaterEmojiPicker::show(select_callback_t callback)
{
mSelectCallback = callback;
openFloater(mKey);
setFocus(TRUE);
}
LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key)
: LLFloater(key)
{
}
BOOL LLFloaterEmojiPicker::postBuild()
{
if (mEmojis = getChild<LLScrollListCtrl>("Emojis"))
{
mEmojis->setDoubleClickCallback(boost::bind(&LLFloaterEmojiPicker::onSelect, this));
mEmojis->clearRows();
const std::map<llwchar, const LLEmojiDescriptor*>& emoji2Descr = LLEmojiDictionary::instance().getEmoji2Descr();
for (const std::pair<llwchar, const LLEmojiDescriptor*>& it : emoji2Descr)
{
LLScrollListItem::Params params;
params.columns.add().column("name").value(it.second->Name);
mEmojis->addRow(new LLEmojiScrollListItem(it.first, params), params);
}
}
return TRUE;
}
LLFloaterEmojiPicker::~LLFloaterEmojiPicker()
{
gFocusMgr.releaseFocusIfNeeded( this );
}
void LLFloaterEmojiPicker::onSelect()
{
if (mEmojis && mSelectCallback)
{
if (LLEmojiScrollListItem* item = dynamic_cast<LLEmojiScrollListItem*>(mEmojis->getFirstSelected()))
{
mSelectCallback(item->getEmoji());
}
}
}
// virtual
BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask)
{
if (key == KEY_RETURN && mask == MASK_NONE)
{
onSelect();
return TRUE;
}
else if (key == KEY_ESCAPE && mask == MASK_NONE)
{
closeFloater();
return TRUE;
}
return LLFloater::handleKeyHere(key, mask);
}

View File

@ -0,0 +1,59 @@
/**
* @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"
class LLFloaterEmojiPicker : public LLFloater
{
public:
// The callback function will be called with an emoji char.
typedef boost::function<void (llwchar)> select_callback_t;
// Call this to select an emoji.
static LLFloaterEmojiPicker* getInstance();
static LLFloaterEmojiPicker* showInstance(select_callback_t callback);
LLFloaterEmojiPicker(const LLSD& key);
virtual ~LLFloaterEmojiPicker();
virtual BOOL postBuild();
void show(select_callback_t callback);
private:
void onSelect();
virtual BOOL handleKeyHere(KEY key, MASK mask);
class LLScrollListCtrl* mEmojis;
select_callback_t mSelectCallback;
std::string mEmojiName;
};
#endif

View File

@ -40,6 +40,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"
@ -250,10 +251,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");
@ -424,6 +428,30 @@ 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::onEmojiSelected, self, _1));
if (LLFloater* root_floater = gFloaterView->getParentFloater(self))
{
root_floater->addDependentFloater(picker);
}
}
else
{
picker->closeFloater();
}
}
}
void LLFloaterIMSessionTab::onEmojiSelected(llwchar emoji)
{
mInputEditor->insertEmoji(emoji);
}
std::string LLFloaterIMSessionTab::appendTime()
{
time_t utc_time;

View File

@ -181,6 +181,7 @@ protected:
LLButton* mExpandCollapseLineBtn;
LLButton* mExpandCollapseBtn;
LLButton* mTearOffBtn;
LLButton* mEmojiBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
LLButton* mAddBtn;
@ -206,6 +207,9 @@ private:
void onInputEditorClicked();
static void onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self);
void onEmojiSelected(llwchar emoji);
bool checkIfTornOff();
bool mIsHostAttached;
bool mHasVisibleBeenInitialized;

View File

@ -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"
@ -329,7 +330,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>);
LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);
LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater);
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>);
@ -337,19 +338,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

View File

@ -205,6 +205,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="Edit_Wrench" file_name="icons/Edit_Wrench.png" preload="false" />
@ -212,7 +213,7 @@ 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_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" />
<texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" />
@ -328,7 +329,7 @@ with the same filename but different name
<texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />
<texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" />
<texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" />
<texture name="Inv_Settings" file_name="icons/Inv_Settings.png" preload="false" />
<texture name="Inv_Settings" file_name="icons/Inv_Settings.png" preload="false" />
<texture name="Inv_SettingsSky" file_name="icons/Inv_SettingsSky.png" preload="false" />
<texture name="Inv_SettingsWater" file_name="icons/Inv_SettingsWater.png" preload="false" />
<texture name="Inv_SettingsDay" file_name="icons/Inv_SettingsDay.png" preload="false" />

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
name="emojipicker"
title="CHOOSE EMOJI"
help_topic="emojipicker"
positioning="cascading"
legacy_header_height="10"
can_resize="false"
layout="topleft"
height="419"
width="200">
<panel
label="Emojis"
name="EmojiPanel"
help_topic="emojipicker"
layout="topleft"
top="4"
left="2"
height="410"
width="196">
<scroll_list
draw_heading="true"
heading_height="28"
follows="all"
layout="topleft"
name="Emojis"
sort_column="0"
height="410">
<columns
label="Look"
name="look"
width="40" />
<columns
label="Name"
name="name"
width="150" />
</scroll_list>
</panel>
</floater>

View File

@ -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"

View File

@ -485,9 +485,9 @@ http://secondlife.com/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>
@ -502,14 +502,14 @@ http://secondlife.com/support for help fixing this problem.
<!-- Chat -->
<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>