Merge branch 'DRTVWR-489' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/skins/default/xui/en/floater_emoji_picker.xmlmeow-7.2.2
commit
e7549d3951
|
|
@ -178,6 +178,10 @@ void LLSearchEditor::setFocus( BOOL b )
|
|||
void LLSearchEditor::onClearButtonClick(const LLSD& data)
|
||||
{
|
||||
setText(LLStringUtil::null);
|
||||
if (mTextChangedCallback)
|
||||
{
|
||||
mTextChangedCallback(this, getValue());
|
||||
}
|
||||
mSearchEditor->onCommit(); // force keystroke callback
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "llagentbenefits.h"
|
||||
#include "llavataractions.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llemojidictionary.h"
|
||||
#include "llfloateremojipicker.h"
|
||||
#include "llfloaterperms.h"
|
||||
#include "llgroupactions.h"
|
||||
#include "llgroupmgr.h"
|
||||
|
|
@ -519,3 +521,16 @@ LLUUID FSCommon::getGroupForRezzing()
|
|||
|
||||
return group_id;
|
||||
}
|
||||
|
||||
void FSCommon::updateUsedEmojis(LLWString text)
|
||||
{
|
||||
LLEmojiDictionary* dictionary = LLEmojiDictionary::getInstance();
|
||||
|
||||
for (llwchar& c : text)
|
||||
{
|
||||
if (dictionary->isEmoji(c))
|
||||
{
|
||||
LLFloaterEmojiPicker::onEmojiUsed(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,6 +93,8 @@ namespace FSCommon
|
|||
bool isFilterEditorKeyCombo(KEY key, MASK mask);
|
||||
|
||||
LLUUID getGroupForRezzing();
|
||||
|
||||
void updateUsedEmojis(LLWString text);
|
||||
};
|
||||
|
||||
#endif // FS_COMMON_H
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@
|
|||
#include "llnotifications.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llnotificationtemplate.h" // <FS:Zi> Viewer version popup
|
||||
#include "llpanelemojicomplete.h"
|
||||
#include "llrootview.h"
|
||||
#include "llscreenchannel.h"
|
||||
#include "llspeakers.h"
|
||||
|
|
@ -376,6 +377,8 @@ void FSFloaterIM::sendMsgFromInputEditor(EChatType type)
|
|||
LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.
|
||||
if (!text.empty())
|
||||
{
|
||||
FSCommon::updateUsedEmojis(text);
|
||||
|
||||
if (type == CHAT_TYPE_OOC)
|
||||
{
|
||||
std::string tempText = wstring_to_utf8str( text );
|
||||
|
|
@ -950,9 +953,22 @@ BOOL FSFloaterIM::postBuild()
|
|||
mInputEditor->enableSingleLineMode(gSavedSettings.getBOOL("FSUseSingleLineChatEntry"));
|
||||
mInputEditor->setCommitCallback(boost::bind(&FSFloaterIM::sendMsgFromInputEditor, this, CHAT_TYPE_NORMAL));
|
||||
|
||||
mEmojiButton = getChild<LLButton>("emoji_panel_btn");
|
||||
mEmojiButton->setLabel(LLUIString(LLWString(1, 128512)));
|
||||
mEmojiButton->setClickedCallback(boost::bind(&FSFloaterIM::onEmojiPanelBtnClicked, this));
|
||||
mEmojiRecentPanelToggleBtn = getChild<LLButton>("emoji_recent_panel_toggle_btn");
|
||||
mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(this); });
|
||||
|
||||
mEmojiRecentPanel = getChild<LLLayoutPanel>("emoji_recent_layout_panel");
|
||||
mEmojiRecentPanel->setVisible(false);
|
||||
|
||||
mEmojiRecentEmptyText = getChildView("emoji_recent_empty_text");
|
||||
mEmojiRecentEmptyText->setVisible(false);
|
||||
|
||||
mEmojiRecentIconsCtrl = getChild<LLPanelEmojiComplete>("emoji_recent_icons_ctrl");
|
||||
mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); });
|
||||
mEmojiRecentIconsCtrl->setVisible(false);
|
||||
|
||||
mEmojiPickerToggleBtn = getChild<LLButton>("emoji_picker_toggle_btn");
|
||||
mEmojiPickerToggleBtn->setLabel(LLUIString(LLWString(1, 128512)));
|
||||
mEmojiPickerToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerToggleBtnClicked(this); });
|
||||
|
||||
getChild<LLButton>("send_chat")->setCommitCallback(boost::bind(&FSFloaterIM::sendMsgFromInputEditor, this, CHAT_TYPE_NORMAL));
|
||||
getChild<LLButton>("chat_search_btn")->setCommitCallback(boost::bind(&FSFloaterIM::onChatSearchButtonClicked, this));
|
||||
|
|
@ -2448,7 +2464,54 @@ bool FSFloaterIM::applyRectControl()
|
|||
return res;
|
||||
}
|
||||
|
||||
void FSFloaterIM::onEmojiPanelBtnClicked(FSFloaterIM* self)
|
||||
void FSFloaterIM::onEmojiRecentPanelToggleBtnClicked(FSFloaterIM* self)
|
||||
{
|
||||
BOOL show = !self->mEmojiRecentPanel->getVisible();
|
||||
if (show)
|
||||
{
|
||||
self->onEmojiRecentPanelOpening();
|
||||
}
|
||||
self->mEmojiRecentPanel->setVisible(show);
|
||||
self->mEmojiRecentPanelToggleBtn->setImageOverlay(show ? "Arrow_Up" : "Arrow_Down");
|
||||
}
|
||||
|
||||
void FSFloaterIM::onEmojiRecentPanelOpening()
|
||||
{
|
||||
std::list<llwchar>& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed();
|
||||
if (recentlyUsed.empty())
|
||||
{
|
||||
mEmojiRecentEmptyText->setVisible(true);
|
||||
mEmojiRecentIconsCtrl->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLWString emojis;
|
||||
for (llwchar emoji : recentlyUsed)
|
||||
{
|
||||
emojis += emoji;
|
||||
}
|
||||
mEmojiRecentIconsCtrl->setEmojis(emojis);
|
||||
mEmojiRecentEmptyText->setVisible(false);
|
||||
mEmojiRecentIconsCtrl->setVisible(true);
|
||||
mEmojiRecentIconsCtrl->setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterIM::onRecentEmojiPicked(const LLSD& value)
|
||||
{
|
||||
LLSD::String str = value.asString();
|
||||
if (str.size())
|
||||
{
|
||||
LLWString wstr = utf8string_to_wstring(str);
|
||||
if (wstr.size())
|
||||
{
|
||||
llwchar emoji = wstr[0];
|
||||
onEmojiPicked(emoji);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterIM::onEmojiPickerToggleBtnClicked(FSFloaterIM* self)
|
||||
{
|
||||
if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ class LLInventoryCategory;
|
|||
class LLInventoryItem;
|
||||
class LLLayoutPanel;
|
||||
class LLLayoutStack;
|
||||
class LLPanelEmojiComplete;
|
||||
class LLTextBox;
|
||||
class LLTextEditor;
|
||||
|
||||
|
||||
typedef boost::signals2::signal<void(const LLUUID& session_id)> floater_showed_signal_t;
|
||||
|
||||
/**
|
||||
|
|
@ -239,7 +239,10 @@ private:
|
|||
bool onChatOptionsVisibleContextMenuItem(const LLSD& userdata);
|
||||
bool onChatOptionsEnableContextMenuItem(const LLSD& userdata);
|
||||
|
||||
static void onEmojiPanelBtnClicked(FSFloaterIM* self);
|
||||
static void onEmojiRecentPanelToggleBtnClicked(FSFloaterIM* self);
|
||||
static void onEmojiPickerToggleBtnClicked(FSFloaterIM* self);
|
||||
void onEmojiRecentPanelOpening();
|
||||
void onRecentEmojiPicked(const LLSD& value);
|
||||
void onEmojiPicked(llwchar emoji);
|
||||
void onEmojiPickerClosed();
|
||||
|
||||
|
|
@ -256,7 +259,11 @@ private:
|
|||
LLLayoutStack* mInputPanels;
|
||||
LLLayoutPanel* mUnreadMessagesNotificationPanel;
|
||||
LLTextBox* mUnreadMessagesNotificationTextBox;
|
||||
LLButton* mEmojiButton;
|
||||
LLButton* mEmojiRecentPanelToggleBtn;
|
||||
LLButton* mEmojiPickerToggleBtn;
|
||||
LLLayoutPanel* mEmojiRecentPanel;
|
||||
LLView* mEmojiRecentEmptyText;
|
||||
LLPanelEmojiComplete* mEmojiRecentIconsCtrl;
|
||||
|
||||
std::string mSavedTitle;
|
||||
LLUIString mTypingStart;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "lllogchat.h"
|
||||
#include "llmenugl.h"
|
||||
#include "llmultigesture.h"
|
||||
#include "llpanelemojicomplete.h"
|
||||
#include "llresizebar.h"
|
||||
#include "llresizehandle.h"
|
||||
#include "llrootview.h"
|
||||
|
|
@ -142,9 +143,22 @@ BOOL FSFloaterNearbyChat::postBuild()
|
|||
mChatLayoutPanelHeight = mChatLayoutPanel->getRect().getHeight();
|
||||
mInputEditorPad = mChatLayoutPanelHeight - mInputEditor->getRect().getHeight();
|
||||
|
||||
mEmojiButton = getChild<LLButton>("emoji_panel_btn");
|
||||
mEmojiButton->setLabel(LLUIString(LLWString(1, 128512)));
|
||||
mEmojiButton->setClickedCallback(boost::bind(&FSFloaterNearbyChat::onEmojiPanelBtnClicked, this));
|
||||
mEmojiRecentPanelToggleBtn = getChild<LLButton>("emoji_recent_panel_toggle_btn");
|
||||
mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(this); });
|
||||
|
||||
mEmojiRecentPanel = getChild<LLLayoutPanel>("emoji_recent_layout_panel");
|
||||
mEmojiRecentPanel->setVisible(false);
|
||||
|
||||
mEmojiRecentEmptyText = getChildView("emoji_recent_empty_text");
|
||||
mEmojiRecentEmptyText->setVisible(false);
|
||||
|
||||
mEmojiRecentIconsCtrl = getChild<LLPanelEmojiComplete>("emoji_recent_icons_ctrl");
|
||||
mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); });
|
||||
mEmojiRecentIconsCtrl->setVisible(false);
|
||||
|
||||
mEmojiPickerToggleBtn = getChild<LLButton>("emoji_picker_toggle_btn");
|
||||
mEmojiPickerToggleBtn->setLabel(LLUIString(LLWString(1, 128512)));
|
||||
mEmojiPickerToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerToggleBtnClicked(this); });
|
||||
|
||||
getChild<LLButton>("chat_history_btn")->setCommitCallback(boost::bind(&FSFloaterNearbyChat::onHistoryButtonClicked, this));
|
||||
getChild<LLButton>("chat_search_btn")->setCommitCallback(boost::bind(&FSFloaterNearbyChat::onSearchButtonClicked, this));
|
||||
|
|
@ -766,6 +780,8 @@ void FSFloaterNearbyChat::sendChat( EChatType type )
|
|||
LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.
|
||||
if (!text.empty())
|
||||
{
|
||||
FSCommon::updateUsedEmojis(text);
|
||||
|
||||
if(type == CHAT_TYPE_OOC)
|
||||
{
|
||||
std::string tempText = wstring_to_utf8str( text );
|
||||
|
|
@ -947,7 +963,54 @@ void FSFloaterNearbyChat::handleMinimized(bool minimized)
|
|||
}
|
||||
}
|
||||
|
||||
void FSFloaterNearbyChat::onEmojiPanelBtnClicked(FSFloaterNearbyChat* self)
|
||||
void FSFloaterNearbyChat::onEmojiRecentPanelToggleBtnClicked(FSFloaterNearbyChat* self)
|
||||
{
|
||||
BOOL show = !self->mEmojiRecentPanel->getVisible();
|
||||
if (show)
|
||||
{
|
||||
self->onEmojiRecentPanelOpening();
|
||||
}
|
||||
self->mEmojiRecentPanel->setVisible(show);
|
||||
self->mEmojiRecentPanelToggleBtn->setImageOverlay(show ? "Arrow_Up" : "Arrow_Down");
|
||||
}
|
||||
|
||||
void FSFloaterNearbyChat::onEmojiRecentPanelOpening()
|
||||
{
|
||||
std::list<llwchar>& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed();
|
||||
if (recentlyUsed.empty())
|
||||
{
|
||||
mEmojiRecentEmptyText->setVisible(true);
|
||||
mEmojiRecentIconsCtrl->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLWString emojis;
|
||||
for (llwchar emoji : recentlyUsed)
|
||||
{
|
||||
emojis += emoji;
|
||||
}
|
||||
mEmojiRecentIconsCtrl->setEmojis(emojis);
|
||||
mEmojiRecentEmptyText->setVisible(false);
|
||||
mEmojiRecentIconsCtrl->setVisible(true);
|
||||
mEmojiRecentIconsCtrl->setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterNearbyChat::onRecentEmojiPicked(const LLSD& value)
|
||||
{
|
||||
LLSD::String str = value.asString();
|
||||
if (str.size())
|
||||
{
|
||||
LLWString wstr = utf8string_to_wstring(str);
|
||||
if (wstr.size())
|
||||
{
|
||||
llwchar emoji = wstr[0];
|
||||
onEmojiPicked(emoji);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterNearbyChat::onEmojiPickerToggleBtnClicked(FSFloaterNearbyChat* self)
|
||||
{
|
||||
if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class LLChatEntry;
|
|||
class LLComboBox;
|
||||
class LLLayoutStack;
|
||||
class LLLayoutPanel;
|
||||
class LLPanelEmojiComplete;
|
||||
class LLResizeBar;
|
||||
class LLTextBox;
|
||||
|
||||
|
|
@ -120,7 +121,10 @@ private:
|
|||
bool onChatOptionsVisibleContextMenuItem(const LLSD& userdata);
|
||||
bool onChatOptionsEnableContextMenuItem(const LLSD& userdata);
|
||||
|
||||
static void onEmojiPanelBtnClicked(FSFloaterNearbyChat* self);
|
||||
static void onEmojiRecentPanelToggleBtnClicked(FSFloaterNearbyChat* self);
|
||||
static void onEmojiPickerToggleBtnClicked(FSFloaterNearbyChat* self);
|
||||
void onEmojiRecentPanelOpening();
|
||||
void onRecentEmojiPicked(const LLSD& value);
|
||||
void onEmojiPicked(llwchar emoji);
|
||||
void onEmojiPickerClosed();
|
||||
|
||||
|
|
@ -129,7 +133,11 @@ private:
|
|||
LLChatEntry* mInputEditor;
|
||||
|
||||
// chat type selector and send chat buttons
|
||||
LLButton* mEmojiButton;
|
||||
LLButton* mEmojiRecentPanelToggleBtn;
|
||||
LLButton* mEmojiPickerToggleBtn;
|
||||
LLLayoutPanel* mEmojiRecentPanel;
|
||||
LLView* mEmojiRecentEmptyText;
|
||||
LLPanelEmojiComplete* mEmojiRecentIconsCtrl;
|
||||
LLButton* mSendChatButton;
|
||||
LLComboBox* mChatTypeCombo;
|
||||
|
||||
|
|
|
|||
|
|
@ -253,6 +253,8 @@ void FSNearbyChat::sendChat(LLWString text, EChatType type)
|
|||
|
||||
if (!text.empty())
|
||||
{
|
||||
FSCommon::updateUsedEmojis(text);
|
||||
|
||||
if (type == CHAT_TYPE_OOC)
|
||||
{
|
||||
text = utf8string_to_wstring(gSavedSettings.getString("FSOOCPrefix") + " ") + text + utf8string_to_wstring(" " + gSavedSettings.getString("FSOOCPostfix"));
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@
|
|||
#include "llbutton.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llemojidictionary.h"
|
||||
#include "llfiltereditor.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "llscrollcontainer.h"
|
||||
#include "llscrollingpanellist.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
|
|
@ -294,9 +294,9 @@ BOOL LLFloaterEmojiPicker::postBuild()
|
|||
mGroups = getChild<LLPanel>("Groups");
|
||||
mBadge = getChild<LLPanel>("Badge");
|
||||
|
||||
mFilter = getChild<LLLineEditor>("Filter");
|
||||
mFilter->setKeystrokeCallback([this](LLLineEditor*, void*) { onSearchKeystroke(); }, NULL);
|
||||
mFilter->setFont(LLViewerChat::getChatFont());
|
||||
mFilter = getChild<LLFilterEditor>("Filter");
|
||||
mFilter->setKeystrokeCallback([this](LLUICtrl*, const LLSD&) { onFilterChanged(); });
|
||||
mFilter->setTextChangedCallback([this](LLUICtrl*, const LLSD&) { onFilterChanged(); });
|
||||
mFilter->setText(sFilterPattern);
|
||||
|
||||
mEmojiScroll = getChild<LLScrollContainer>("EmojiGridContainer");
|
||||
|
|
@ -588,7 +588,7 @@ void LLFloaterEmojiPicker::onGroupButtonClick(LLUICtrl* ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::onSearchKeystroke()
|
||||
void LLFloaterEmojiPicker::onFilterChanged()
|
||||
{
|
||||
sFilterPattern = mFilter->getText();
|
||||
fillEmojis();
|
||||
|
|
@ -669,7 +669,6 @@ void LLFloaterEmojiPicker::onEmojiMouseUp(LLUICtrl* ctrl)
|
|||
{
|
||||
if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl))
|
||||
{
|
||||
onEmojiUsed(icon->getEmoji());
|
||||
if (mEmojiPickCallback)
|
||||
{
|
||||
mEmojiPickCallback(icon->getEmoji());
|
||||
|
|
@ -723,6 +722,14 @@ void LLFloaterEmojiPicker::closeFloater(bool app_quitting)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
std::list<llwchar>& LLFloaterEmojiPicker::getRecentlyUsed()
|
||||
{
|
||||
loadState();
|
||||
return sRecentlyUsed;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterEmojiPicker::onEmojiUsed(llwchar emoji)
|
||||
{
|
||||
// Update sRecentlyUsed
|
||||
|
|
@ -762,6 +769,7 @@ void LLFloaterEmojiPicker::onEmojiUsed(llwchar emoji)
|
|||
sFrequentlyUsed.push_back(std::make_pair(emoji, 1));
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterEmojiPicker::loadState()
|
||||
{
|
||||
if (!sStateFileName.empty())
|
||||
|
|
@ -844,6 +852,7 @@ void LLFloaterEmojiPicker::loadState()
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterEmojiPicker::saveState()
|
||||
{
|
||||
if (sStateFileName.empty())
|
||||
|
|
|
|||
|
|
@ -54,13 +54,18 @@ public:
|
|||
|
||||
virtual void closeFloater(bool app_quitting = false) override;
|
||||
|
||||
static std::list<llwchar>& getRecentlyUsed();
|
||||
static void onEmojiUsed(llwchar emoji);
|
||||
static void loadState();
|
||||
static void saveState();
|
||||
|
||||
private:
|
||||
void fillGroups();
|
||||
void moveGroups();
|
||||
void fillEmojis(bool fromResize = false);
|
||||
|
||||
void onGroupButtonClick(LLUICtrl* ctrl);
|
||||
void onSearchKeystroke();
|
||||
void onFilterChanged();
|
||||
void onGridMouseEnter();
|
||||
void onGridMouseLeave();
|
||||
void onGroupButtonMouseEnter(LLUICtrl* ctrl);
|
||||
|
|
@ -75,13 +80,9 @@ private:
|
|||
|
||||
virtual BOOL handleKeyHere(KEY key, MASK mask) override;
|
||||
|
||||
void onEmojiUsed(llwchar emoji);
|
||||
void loadState();
|
||||
void saveState();
|
||||
|
||||
class LLPanel* mGroups { nullptr };
|
||||
class LLPanel* mBadge { nullptr };
|
||||
class LLLineEditor* mFilter { nullptr };
|
||||
class LLFilterEditor* mFilter { nullptr };
|
||||
class LLScrollContainer* mEmojiScroll { nullptr };
|
||||
class LLScrollingPanelList* mEmojiGrid { nullptr };
|
||||
class LLEmojiPreviewPanel* mPreview { nullptr };
|
||||
|
|
|
|||
|
|
@ -601,6 +601,8 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
|
|||
S32 channel = 0;
|
||||
stripChannelNumber(text, &channel);
|
||||
|
||||
updateUsedEmojis(text);
|
||||
|
||||
std::string utf8text = wstring_to_utf8str(text);
|
||||
// Try to trigger a gesture, if not chat to a script.
|
||||
std::string utf8_revised_text;
|
||||
|
|
|
|||
|
|
@ -254,6 +254,8 @@ void LLFloaterIMSession::sendMsgFromInputEditor()
|
|||
LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.
|
||||
if(!text.empty())
|
||||
{
|
||||
updateUsedEmojis(text);
|
||||
|
||||
// Truncate and convert to UTF8 for transport
|
||||
std::string utf8_text = wstring_to_utf8str(text);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,19 +35,21 @@
|
|||
#include "llagentcamera.h"
|
||||
#include "llavataractions.h"
|
||||
#include "llavatariconctrl.h"
|
||||
#include "llgroupiconctrl.h"
|
||||
#include "llchatentry.h"
|
||||
#include "llchathistory.h"
|
||||
#include "llchiclet.h"
|
||||
#include "llchicletbar.h"
|
||||
#include "lldraghandle.h"
|
||||
#include "llemojidictionary.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloateremojipicker.h"
|
||||
#include "llfloaterimsession.h"
|
||||
#include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container
|
||||
#include "lllayoutstack.h"
|
||||
#include "lltoolbarview.h"
|
||||
#include "llfloaterimnearbychat.h"
|
||||
#include "llgroupiconctrl.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "llpanelemojicomplete.h"
|
||||
#include "lltoolbarview.h"
|
||||
|
||||
const F32 REFRESH_INTERVAL = 1.0f;
|
||||
const std::string ICN_GROUP("group_chat_icon");
|
||||
|
|
@ -59,7 +61,7 @@ void cb_group_do_nothing()
|
|||
}
|
||||
|
||||
LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
|
||||
: LLTransientDockableFloater(NULL, false, session_id),
|
||||
: super(NULL, false, session_id),
|
||||
mIsP2PChat(false),
|
||||
mExpandCollapseBtn(NULL),
|
||||
mTearOffBtn(NULL),
|
||||
|
|
@ -78,7 +80,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
|
|||
mInputPanels(NULL),
|
||||
mChatLayoutPanelHeight(0)
|
||||
{
|
||||
setAutoFocus(FALSE);
|
||||
setAutoFocus(FALSE);
|
||||
mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
|
||||
|
||||
mCommitCallbackRegistrar.add("IMSession.Menu.Action",
|
||||
|
|
@ -91,12 +93,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
|
|||
boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2));
|
||||
|
||||
// Right click menu handling
|
||||
mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2));
|
||||
mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2));
|
||||
mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2));
|
||||
mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing));
|
||||
mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2));
|
||||
mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2));
|
||||
mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2));
|
||||
mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing));
|
||||
|
||||
mMinFloaterHeight = getMinHeight();
|
||||
mMinFloaterHeight = getMinHeight();
|
||||
}
|
||||
|
||||
LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
|
||||
|
|
@ -104,7 +106,7 @@ LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
|
|||
delete mRefreshTimer;
|
||||
}
|
||||
|
||||
//static
|
||||
// static
|
||||
LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uuid)
|
||||
{
|
||||
LLFloaterIMSessionTab* conv;
|
||||
|
|
@ -121,7 +123,7 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uui
|
|||
return conv;
|
||||
};
|
||||
|
||||
//static
|
||||
// static
|
||||
LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid)
|
||||
{
|
||||
LLFloaterIMSessionTab* conv;
|
||||
|
|
@ -137,14 +139,16 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid
|
|||
}
|
||||
|
||||
return conv;
|
||||
|
||||
};
|
||||
|
||||
// virtual
|
||||
void LLFloaterIMSessionTab::setVisible(BOOL visible)
|
||||
{
|
||||
if(visible && !mHasVisibleBeenInitialized)
|
||||
if (visible && !mHasVisibleBeenInitialized)
|
||||
{
|
||||
mHasVisibleBeenInitialized = true;
|
||||
if(!gAgentCamera.cameraMouselook())
|
||||
if (!gAgentCamera.cameraMouselook())
|
||||
{
|
||||
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);
|
||||
}
|
||||
|
|
@ -158,27 +162,26 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible)
|
|||
mInputButtonPanel->setVisible(isTornOff());
|
||||
}
|
||||
|
||||
LLTransientDockableFloater::setVisible(visible);
|
||||
super::setVisible(visible);
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
// virtual
|
||||
void LLFloaterIMSessionTab::setFocus(BOOL focus)
|
||||
{
|
||||
LLTransientDockableFloater::setFocus(focus);
|
||||
super::setFocus(focus);
|
||||
|
||||
//Redirect focus to input editor
|
||||
if (focus)
|
||||
// Redirect focus to input editor
|
||||
if (focus)
|
||||
{
|
||||
updateMessages();
|
||||
updateMessages();
|
||||
|
||||
if (mInputEditor)
|
||||
{
|
||||
mInputEditor->setFocus(TRUE);
|
||||
}
|
||||
if (mInputEditor)
|
||||
{
|
||||
mInputEditor->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
|
||||
{
|
||||
if ((session_id.notNull() && !gIMMgr->hasSession(session_id))
|
||||
|
|
@ -223,44 +226,58 @@ void LLFloaterIMSessionTab::assignResizeLimits()
|
|||
{
|
||||
bool is_participants_pane_collapsed = mParticipantListPanel->isCollapsed();
|
||||
|
||||
// disable a layoutstack's functionality when participant list panel is collapsed
|
||||
// disable a layoutstack's functionality when participant list panel is collapsed
|
||||
mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);
|
||||
|
||||
S32 participants_pane_target_width = is_participants_pane_collapsed?
|
||||
0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());
|
||||
S32 participants_pane_target_width = is_participants_pane_collapsed?
|
||||
0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());
|
||||
|
||||
S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
|
||||
S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
|
||||
|
||||
setResizeLimits(new_min_width, getMinHeight());
|
||||
|
||||
this->mParticipantListAndHistoryStack->updateLayout();
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLFloaterIMSessionTab::postBuild()
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
mBodyStack = getChild<LLLayoutStack>("main_stack");
|
||||
mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels");
|
||||
mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels");
|
||||
|
||||
mCloseBtn = getChild<LLButton>("close_btn");
|
||||
mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));
|
||||
mCloseBtn->setCommitCallback([this](LLUICtrl*, const LLSD&) { onClickClose(this); });
|
||||
|
||||
mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
|
||||
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this));
|
||||
mExpandCollapseBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onSlide(this); });
|
||||
|
||||
mExpandCollapseLineBtn = getChild<LLButton>("minz_btn");
|
||||
mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this));
|
||||
mExpandCollapseLineBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onCollapseToLine(this); });
|
||||
|
||||
mTearOffBtn = getChild<LLButton>("tear_off_btn");
|
||||
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
|
||||
|
||||
mEmojiBtn = getChild<LLButton>("emoji_panel_btn");
|
||||
mEmojiBtn->setLabel(LLUIString(LLWString(1, 128512)));
|
||||
mEmojiBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onEmojiPanelBtnClicked, this));
|
||||
mEmojiRecentPanelToggleBtn = getChild<LLButton>("emoji_recent_panel_toggle_btn");
|
||||
mEmojiRecentPanelToggleBtn->setLabel(LLUIString(LLWString(1, 128512)));
|
||||
mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(this); });
|
||||
|
||||
mEmojiRecentPanel = getChild<LLLayoutPanel>("emoji_recent_layout_panel");
|
||||
mEmojiRecentPanel->setVisible(false);
|
||||
|
||||
mEmojiRecentEmptyText = getChildView("emoji_recent_empty_text");
|
||||
mEmojiRecentEmptyText->setVisible(false);
|
||||
|
||||
mEmojiRecentIconsCtrl = getChild<LLPanelEmojiComplete>("emoji_recent_icons_ctrl");
|
||||
mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); });
|
||||
mEmojiRecentIconsCtrl->setVisible(false);
|
||||
|
||||
mEmojiPickerToggleBtn = getChild<LLButton>("emoji_picker_toggle_btn");
|
||||
mEmojiPickerToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerToggleBtnClicked(this); });
|
||||
|
||||
mGearBtn = getChild<LLButton>("gear_btn");
|
||||
mAddBtn = getChild<LLButton>("add_btn");
|
||||
mAddBtn = getChild<LLButton>("add_btn");
|
||||
mVoiceButton = getChild<LLButton>("voice_call_btn");
|
||||
|
||||
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
|
||||
|
|
@ -314,17 +331,17 @@ BOOL LLFloaterIMSessionTab::postBuild()
|
|||
|
||||
// Create the root using an ad-hoc base item
|
||||
LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel);
|
||||
LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
|
||||
p.rect = LLRect(0, 0, getRect().getWidth(), 0);
|
||||
p.parent_panel = mParticipantListPanel;
|
||||
p.listener = base_item;
|
||||
p.view_model = &mConversationViewModel;
|
||||
p.root = NULL;
|
||||
p.use_ellipses = true;
|
||||
p.options_menu = "menu_conversation.xml";
|
||||
p.name = "root";
|
||||
LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
|
||||
p.rect = LLRect(0, 0, getRect().getWidth(), 0);
|
||||
p.parent_panel = mParticipantListPanel;
|
||||
p.listener = base_item;
|
||||
p.view_model = &mConversationViewModel;
|
||||
p.root = NULL;
|
||||
p.use_ellipses = true;
|
||||
p.options_menu = "menu_conversation.xml";
|
||||
p.name = "root";
|
||||
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
|
||||
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
|
||||
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
|
||||
mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);
|
||||
// Attach that root to the scroller
|
||||
mScroller->addChild(mConversationsRoot);
|
||||
|
|
@ -364,6 +381,7 @@ LLParticipantList* LLFloaterIMSessionTab::getParticipantList()
|
|||
return dynamic_cast<LLParticipantList*>(LLFloaterIMContainer::getInstance()->getSessionModel(mSessionID));
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterIMSessionTab::draw()
|
||||
{
|
||||
if (mRefreshTimer->hasExpired())
|
||||
|
|
@ -388,23 +406,24 @@ void LLFloaterIMSessionTab::draw()
|
|||
mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
LLTransientDockableFloater::draw();
|
||||
super::draw();
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::enableDisableCallBtn()
|
||||
{
|
||||
if (LLVoiceClient::instanceExists() && mVoiceButton)
|
||||
{
|
||||
mVoiceButton->setEnabled(
|
||||
mSessionID.notNull()
|
||||
&& mSession
|
||||
&& mSession->mSessionInitialized
|
||||
&& LLVoiceClient::getInstance()->voiceEnabled()
|
||||
&& LLVoiceClient::getInstance()->isVoiceWorking()
|
||||
&& mSession->mCallBackEnabled);
|
||||
}
|
||||
if (LLVoiceClient::instanceExists() && mVoiceButton)
|
||||
{
|
||||
mVoiceButton->setEnabled(
|
||||
mSessionID.notNull()
|
||||
&& mSession
|
||||
&& mSession->mSessionInitialized
|
||||
&& LLVoiceClient::getInstance()->voiceEnabled()
|
||||
&& LLVoiceClient::getInstance()->isVoiceWorking()
|
||||
&& mSession->mCallBackEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterIMSessionTab::onFocusReceived()
|
||||
{
|
||||
setBackgroundOpaque(true);
|
||||
|
|
@ -414,13 +433,14 @@ void LLFloaterIMSessionTab::onFocusReceived()
|
|||
LLIMModel::instance().sendNoUnreadMessages(mSessionID);
|
||||
}
|
||||
|
||||
LLTransientDockableFloater::onFocusReceived();
|
||||
super::onFocusReceived();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterIMSessionTab::onFocusLost()
|
||||
{
|
||||
setBackgroundOpaque(false);
|
||||
LLTransientDockableFloater::onFocusLost();
|
||||
super::onFocusLost();
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onInputEditorClicked()
|
||||
|
|
@ -433,7 +453,17 @@ void LLFloaterIMSessionTab::onInputEditorClicked()
|
|||
gToolBarView->flashCommand(LLCommandId("chat"), false);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self)
|
||||
void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self)
|
||||
{
|
||||
BOOL show = !self->mEmojiRecentPanel->getVisible();
|
||||
if (show)
|
||||
{
|
||||
self->onEmojiRecentPanelOpening();
|
||||
}
|
||||
self->mEmojiRecentPanel->setVisible(show);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPickerToggleBtnClicked(LLFloaterIMSessionTab* self)
|
||||
{
|
||||
if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance())
|
||||
{
|
||||
|
|
@ -454,6 +484,43 @@ void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self)
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiRecentPanelOpening()
|
||||
{
|
||||
std::list<llwchar>& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed();
|
||||
if (recentlyUsed.empty())
|
||||
{
|
||||
mEmojiRecentEmptyText->setVisible(true);
|
||||
mEmojiRecentIconsCtrl->setVisible(false);
|
||||
mEmojiPickerToggleBtn->setFocus(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLWString emojis;
|
||||
for (llwchar emoji : recentlyUsed)
|
||||
{
|
||||
emojis += emoji;
|
||||
}
|
||||
mEmojiRecentIconsCtrl->setEmojis(emojis);
|
||||
mEmojiRecentEmptyText->setVisible(false);
|
||||
mEmojiRecentIconsCtrl->setVisible(true);
|
||||
mEmojiRecentIconsCtrl->setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onRecentEmojiPicked(const LLSD& value)
|
||||
{
|
||||
LLSD::String str = value.asString();
|
||||
if (str.size())
|
||||
{
|
||||
LLWString wstr = utf8string_to_wstring(str);
|
||||
if (wstr.size())
|
||||
{
|
||||
llwchar emoji = wstr[0];
|
||||
onEmojiPicked(emoji);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onEmojiPicked(llwchar emoji)
|
||||
{
|
||||
mInputEditor->insertEmoji(emoji);
|
||||
|
|
@ -464,6 +531,12 @@ void LLFloaterIMSessionTab::onEmojiPickerClosed()
|
|||
mInputEditor->setFocus(TRUE);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::closeFloater(bool app_quitting)
|
||||
{
|
||||
LLFloaterEmojiPicker::saveState();
|
||||
super::closeFloater(app_quitting);
|
||||
}
|
||||
|
||||
std::string LLFloaterIMSessionTab::appendTime()
|
||||
{
|
||||
std::string timeStr = "[" + LLTrans::getString("TimeHour") + "]:"
|
||||
|
|
@ -505,6 +578,20 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD& args)
|
|||
mChatHistory->appendMessage(chat, chat_args);
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::updateUsedEmojis(LLWString text)
|
||||
{
|
||||
LLEmojiDictionary* dictionary = LLEmojiDictionary::getInstance();
|
||||
llassert_always(dictionary);
|
||||
|
||||
for (llwchar& c : text)
|
||||
{
|
||||
if (dictionary->isEmoji(c))
|
||||
{
|
||||
LLFloaterEmojiPicker::onEmojiUsed(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT("Build Conversation View");
|
||||
void LLFloaterIMSessionTab::buildConversationViewParticipant()
|
||||
{
|
||||
|
|
@ -532,10 +619,10 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
|
|||
while (current_participant_model != end_participant_model)
|
||||
{
|
||||
LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model);
|
||||
if (participant_model)
|
||||
{
|
||||
addConversationViewParticipant(participant_model);
|
||||
}
|
||||
if (participant_model)
|
||||
{
|
||||
addConversationViewParticipant(participant_model);
|
||||
}
|
||||
current_participant_model++;
|
||||
}
|
||||
}
|
||||
|
|
@ -555,10 +642,10 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p
|
|||
// If not already present, create the participant view and attach it to the root, otherwise, just refresh it
|
||||
if (widget)
|
||||
{
|
||||
if (update_view)
|
||||
{
|
||||
updateConversationViewParticipant(uuid); // overkill?
|
||||
}
|
||||
if (update_view)
|
||||
{
|
||||
updateConversationViewParticipant(uuid); // overkill?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -608,11 +695,11 @@ void LLFloaterIMSessionTab::refreshConversation()
|
|||
{
|
||||
participants_uuids.push_back(widget_it->first);
|
||||
}
|
||||
if (widget_it->second->getViewModelItem())
|
||||
{
|
||||
widget_it->second->refresh();
|
||||
widget_it->second->setVisible(TRUE);
|
||||
}
|
||||
if (widget_it->second->getViewModelItem())
|
||||
{
|
||||
widget_it->second->refresh();
|
||||
widget_it->second->setVisible(TRUE);
|
||||
}
|
||||
++widget_it;
|
||||
}
|
||||
if (is_ad_hoc || mIsP2PChat)
|
||||
|
|
@ -668,7 +755,7 @@ void LLFloaterIMSessionTab::refreshConversation()
|
|||
// Copied from LLFloaterIMContainer::createConversationViewParticipant(). Refactor opportunity!
|
||||
LLConversationViewParticipant* LLFloaterIMSessionTab::createConversationViewParticipant(LLConversationItem* item)
|
||||
{
|
||||
LLRect panel_rect = mParticipantListPanel->getRect();
|
||||
LLRect panel_rect = mParticipantListPanel->getRect();
|
||||
|
||||
LLConversationViewParticipant::Params params;
|
||||
params.name = item->getDisplayName();
|
||||
|
|
@ -796,7 +883,7 @@ void LLFloaterIMSessionTab::hideAllStandardButtons()
|
|||
void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
||||
{
|
||||
// prevent start conversation before its container
|
||||
LLFloaterIMContainer::getInstance();
|
||||
LLFloaterIMContainer::getInstance();
|
||||
|
||||
bool is_not_torn_off = !checkIfTornOff();
|
||||
if (is_not_torn_off)
|
||||
|
|
@ -813,12 +900,12 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
|||
&& !mIsP2PChat;
|
||||
|
||||
mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible);
|
||||
mParticipantListPanel->setVisible(is_participant_list_visible);
|
||||
mParticipantListPanel->setVisible(is_participant_list_visible);
|
||||
|
||||
// Display collapse image (<<) if the floater is hosted
|
||||
// or if it is torn off but has an open control panel.
|
||||
bool is_expanded = is_not_torn_off || is_participant_list_visible;
|
||||
|
||||
|
||||
mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));
|
||||
mExpandCollapseBtn->setToolTip(
|
||||
is_not_torn_off?
|
||||
|
|
@ -847,10 +934,10 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
|||
|
||||
void LLFloaterIMSessionTab::forceReshape()
|
||||
{
|
||||
LLRect floater_rect = getRect();
|
||||
reshape(llmax(floater_rect.getWidth(), this->getMinWidth()),
|
||||
llmax(floater_rect.getHeight(), this->getMinHeight()),
|
||||
true);
|
||||
LLRect floater_rect = getRect();
|
||||
reshape(llmax(floater_rect.getWidth(), this->getMinWidth()),
|
||||
llmax(floater_rect.getHeight(), this->getMinHeight()),
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -876,7 +963,7 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/*
|
|||
LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
|
||||
if (nearby_chat)
|
||||
{
|
||||
nearby_chat->reloadMessages(clean_messages);
|
||||
nearby_chat->reloadMessages(clean_messages);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -922,15 +1009,15 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
|
|||
{
|
||||
if (!self->mIsP2PChat)
|
||||
{
|
||||
// The state must toggle the collapsed state of the panel
|
||||
should_be_expanded = self->mParticipantListPanel->isCollapsed();
|
||||
// The state must toggle the collapsed state of the panel
|
||||
should_be_expanded = self->mParticipantListPanel->isCollapsed();
|
||||
|
||||
// Update the expand/collapse flag of the participant list panel and save it
|
||||
gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded);
|
||||
self->mIsParticipantListExpanded = should_be_expanded;
|
||||
|
||||
// Refresh for immediate feedback
|
||||
self->refreshConversation();
|
||||
gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded);
|
||||
self->mIsParticipantListExpanded = should_be_expanded;
|
||||
|
||||
// Refresh for immediate feedback
|
||||
self->refreshConversation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -967,12 +1054,12 @@ void LLFloaterIMSessionTab::reshapeFloater(bool collapse)
|
|||
+ mChatLayoutPanel->getRect().getHeight() - mChatLayoutPanelHeight + 2;
|
||||
floater_rect.mTop -= height;
|
||||
|
||||
setResizeLimits(getMinWidth(), floater_rect.getHeight());
|
||||
setResizeLimits(getMinWidth(), floater_rect.getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
|
||||
setResizeLimits(getMinWidth(), mMinFloaterHeight);
|
||||
setResizeLimits(getMinWidth(), mMinFloaterHeight);
|
||||
}
|
||||
|
||||
enableResizeCtrls(true, true, !collapse);
|
||||
|
|
@ -997,7 +1084,7 @@ void LLFloaterIMSessionTab::restoreFloater()
|
|||
setShape(floater_rect, true);
|
||||
mBodyStack->updateLayout();
|
||||
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
|
||||
setResizeLimits(getMinWidth(), mMinFloaterHeight);
|
||||
setResizeLimits(getMinWidth(), mMinFloaterHeight);
|
||||
setMessagePaneExpanded(true);
|
||||
saveCollapsedState();
|
||||
mInputEditor->enableSingleLineMode(false);
|
||||
|
|
@ -1023,8 +1110,8 @@ void LLFloaterIMSessionTab::onTearOffClicked()
|
|||
{
|
||||
restoreFloater();
|
||||
setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE);
|
||||
mSaveRect = isTornOff();
|
||||
initRectControl();
|
||||
mSaveRect = isTornOff();
|
||||
initRectControl();
|
||||
LLFloater::onClickTearOff(this);
|
||||
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
|
||||
|
|
@ -1114,8 +1201,8 @@ bool LLFloaterIMSessionTab::checkIfTornOff()
|
|||
void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata)
|
||||
{
|
||||
// Get the list of selected items in the tab
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
getSelectedUUIDs(selected_uuids);
|
||||
|
||||
// Perform the command (IM, profile, etc...) on the list using the general conversation container method
|
||||
|
|
@ -1127,8 +1214,8 @@ void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata)
|
|||
bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata)
|
||||
{
|
||||
// Get the list of selected items in the tab
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
getSelectedUUIDs(selected_uuids);
|
||||
|
||||
// Perform the item enable test on the list using the general conversation container method
|
||||
|
|
@ -1139,8 +1226,8 @@ bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata)
|
|||
bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata)
|
||||
{
|
||||
// Get the list of selected items in the tab
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
getSelectedUUIDs(selected_uuids);
|
||||
|
||||
// Perform the item check on the list using the general conversation container method
|
||||
|
|
@ -1150,19 +1237,19 @@ bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata)
|
|||
|
||||
void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids)
|
||||
{
|
||||
const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList();
|
||||
const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList();
|
||||
|
||||
std::set<LLFolderViewItem*>::const_iterator it = selected_items.begin();
|
||||
const std::set<LLFolderViewItem*>::const_iterator it_end = selected_items.end();
|
||||
std::set<LLFolderViewItem*>::const_iterator it = selected_items.begin();
|
||||
const std::set<LLFolderViewItem*>::const_iterator it_end = selected_items.end();
|
||||
|
||||
for (; it != it_end; ++it)
|
||||
{
|
||||
LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem());
|
||||
if (conversation_item)
|
||||
{
|
||||
selected_uuids.push_back(conversation_item->getUUID());
|
||||
}
|
||||
}
|
||||
for (; it != it_end; ++it)
|
||||
{
|
||||
LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem());
|
||||
if (conversation_item)
|
||||
{
|
||||
selected_uuids.push_back(conversation_item->getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()
|
||||
|
|
@ -1170,8 +1257,8 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()
|
|||
LLConversationItem *conversationItem = NULL;
|
||||
|
||||
if(mConversationsRoot &&
|
||||
mConversationsRoot->getCurSelectedItem() &&
|
||||
mConversationsRoot->getCurSelectedItem()->getViewModelItem())
|
||||
mConversationsRoot->getCurSelectedItem() &&
|
||||
mConversationsRoot->getCurSelectedItem()->getViewModelItem())
|
||||
{
|
||||
conversationItem = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem()) ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,10 +43,12 @@
|
|||
class LLPanelChatControlPanel;
|
||||
class LLChatEntry;
|
||||
class LLChatHistory;
|
||||
class LLPanelEmojiComplete;
|
||||
|
||||
class LLFloaterIMSessionTab
|
||||
: public LLTransientDockableFloater
|
||||
{
|
||||
using super = LLTransientDockableFloater;
|
||||
|
||||
public:
|
||||
LOG_CLASS(LLFloaterIMSessionTab);
|
||||
|
|
@ -70,9 +72,8 @@ public:
|
|||
bool isHostAttached() {return mIsHostAttached;}
|
||||
void setHostAttached(bool is_attached) {mIsHostAttached = is_attached;}
|
||||
|
||||
static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid);
|
||||
static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid);
|
||||
|
||||
static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid);
|
||||
static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid);
|
||||
|
||||
bool isNearbyChat() {return mIsNearbyChat;}
|
||||
|
||||
|
|
@ -82,6 +83,7 @@ public:
|
|||
/*virtual*/ void draw();
|
||||
/*virtual*/ void setVisible(BOOL visible);
|
||||
/*virtual*/ void setFocus(BOOL focus);
|
||||
/*virtual*/ void closeFloater(bool app_quitting = false);
|
||||
|
||||
// Handle the left hand participant list widgets
|
||||
void addConversationViewParticipant(LLConversationItem* item, bool update_view = true);
|
||||
|
|
@ -138,8 +140,8 @@ protected:
|
|||
virtual void enableDisableCallBtn();
|
||||
|
||||
// process focus events to set a currently active session
|
||||
/* virtual */ void onFocusLost();
|
||||
/* virtual */ void onFocusReceived();
|
||||
/* virtual */ void onFocusLost();
|
||||
|
||||
// prepare chat's params and out one message to chatHistory
|
||||
void appendMessage(const LLChat& chat, const LLSD& args = LLSD());
|
||||
|
|
@ -147,6 +149,8 @@ protected:
|
|||
std::string appendTime();
|
||||
void assignResizeLimits();
|
||||
|
||||
void updateUsedEmojis(LLWString text);
|
||||
|
||||
S32 mFloaterExtraWidth;
|
||||
|
||||
bool mIsNearbyChat;
|
||||
|
|
@ -154,8 +158,7 @@ protected:
|
|||
|
||||
bool mMessagePaneExpanded;
|
||||
bool mIsParticipantListExpanded;
|
||||
S32 mMinFloaterHeight;
|
||||
|
||||
S32 mMinFloaterHeight;
|
||||
|
||||
LLIMModel::LLIMSession* mSession;
|
||||
|
||||
|
|
@ -170,33 +173,37 @@ protected:
|
|||
LLLayoutPanel* mContentPanel;
|
||||
LLLayoutPanel* mToolbarPanel;
|
||||
LLLayoutPanel* mInputButtonPanel;
|
||||
LLLayoutPanel* mEmojiRecentPanel;
|
||||
LLView* mEmojiRecentEmptyText;
|
||||
LLPanelEmojiComplete* mEmojiRecentIconsCtrl;
|
||||
LLParticipantList* getParticipantList();
|
||||
conversations_widgets_map mConversationsWidgets;
|
||||
LLConversationViewModel mConversationViewModel;
|
||||
LLFolderView* mConversationsRoot;
|
||||
LLScrollContainer* mScroller;
|
||||
|
||||
LLChatHistory* mChatHistory;
|
||||
LLChatHistory* mChatHistory;
|
||||
LLChatEntry* mInputEditor;
|
||||
LLLayoutPanel * mChatLayoutPanel;
|
||||
LLLayoutStack * mInputPanels;
|
||||
LLLayoutPanel* mChatLayoutPanel;
|
||||
LLLayoutStack* mInputPanels;
|
||||
|
||||
LLButton* mExpandCollapseLineBtn;
|
||||
LLButton* mExpandCollapseBtn;
|
||||
LLButton* mTearOffBtn;
|
||||
LLButton* mEmojiBtn;
|
||||
LLButton* mEmojiRecentPanelToggleBtn;
|
||||
LLButton* mEmojiPickerToggleBtn;
|
||||
LLButton* mCloseBtn;
|
||||
LLButton* mGearBtn;
|
||||
LLButton* mAddBtn;
|
||||
LLButton* mVoiceButton;
|
||||
LLButton* mVoiceButton;
|
||||
|
||||
private:
|
||||
// Handling selection and contextual menu
|
||||
void doToSelected(const LLSD& userdata);
|
||||
bool enableContextMenuItem(const LLSD& userdata);
|
||||
bool checkContextMenuItem(const LLSD& userdata);
|
||||
void doToSelected(const LLSD& userdata);
|
||||
bool enableContextMenuItem(const LLSD& userdata);
|
||||
bool checkContextMenuItem(const LLSD& userdata);
|
||||
|
||||
void getSelectedUUIDs(uuid_vec_t& selected_uuids);
|
||||
void getSelectedUUIDs(uuid_vec_t& selected_uuids);
|
||||
|
||||
/// Refreshes the floater at a constant rate.
|
||||
virtual void refresh() = 0;
|
||||
|
|
@ -210,13 +217,16 @@ private:
|
|||
|
||||
void onInputEditorClicked();
|
||||
|
||||
static void onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self);
|
||||
static void onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self);
|
||||
static void onEmojiPickerToggleBtnClicked(LLFloaterIMSessionTab* self);
|
||||
void onEmojiRecentPanelOpening();
|
||||
void onRecentEmojiPicked(const LLSD& value);
|
||||
void onEmojiPicked(llwchar emoji);
|
||||
void onEmojiPickerClosed();
|
||||
|
||||
bool checkIfTornOff();
|
||||
bool mIsHostAttached;
|
||||
bool mHasVisibleBeenInitialized;
|
||||
bool mIsHostAttached;
|
||||
bool mHasVisibleBeenInitialized;
|
||||
|
||||
LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called.
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ static LLDefaultChildRegistry::Register<LLPanelEmojiComplete> r("emoji_complete"
|
|||
|
||||
LLPanelEmojiComplete::Params::Params()
|
||||
: autosize("autosize")
|
||||
, noscroll("noscroll")
|
||||
, max_emoji("max_emoji")
|
||||
, padding("padding")
|
||||
, selected_image("selected_image")
|
||||
|
|
@ -50,6 +51,7 @@ LLPanelEmojiComplete::Params::Params()
|
|||
LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p)
|
||||
: LLUICtrl(p)
|
||||
, mAutoSize(p.autosize)
|
||||
, mNoScroll(p.noscroll)
|
||||
, mMaxVisible(p.max_emoji)
|
||||
, mPadding(p.padding)
|
||||
, mSelectedImage(p.selected_image)
|
||||
|
|
@ -152,7 +154,7 @@ BOOL LLPanelEmojiComplete::handleMouseUp(S32 x, S32 y, MASK mask)
|
|||
|
||||
void LLPanelEmojiComplete::onCommit()
|
||||
{
|
||||
if (npos != mCurSelected)
|
||||
if (mCurSelected < mEmojis.size())
|
||||
{
|
||||
LLWString wstr;
|
||||
wstr.push_back(mEmojis.at(mCurSelected));
|
||||
|
|
@ -167,6 +169,14 @@ void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_paren
|
|||
updateConstraints();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::setEmojis(const LLWString& emojis)
|
||||
{
|
||||
mEmojis = emojis;
|
||||
mCurSelected = 0;
|
||||
|
||||
onEmojisChanged();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::setEmojiHint(const std::string& hint)
|
||||
{
|
||||
llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0;
|
||||
|
|
@ -175,6 +185,11 @@ void LLPanelEmojiComplete::setEmojiHint(const std::string& hint)
|
|||
size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos;
|
||||
mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0;
|
||||
|
||||
onEmojisChanged();
|
||||
}
|
||||
|
||||
void LLPanelEmojiComplete::onEmojisChanged()
|
||||
{
|
||||
if (mAutoSize)
|
||||
{
|
||||
mVisibleEmojis = (U16)std::min(mEmojis.size(), mMaxVisible);
|
||||
|
|
@ -233,9 +248,13 @@ void LLPanelEmojiComplete::updateConstraints()
|
|||
void LLPanelEmojiComplete::updateScrollPos()
|
||||
{
|
||||
const size_t cntEmoji = mEmojis.size();
|
||||
if (0 == cntEmoji || cntEmoji < mVisibleEmojis || 0 == mCurSelected)
|
||||
if (mNoScroll || 0 == cntEmoji || cntEmoji < mVisibleEmojis || 0 == mCurSelected)
|
||||
{
|
||||
mScrollPos = 0;
|
||||
if (mCurSelected >= mVisibleEmojis)
|
||||
{
|
||||
mCurSelected = mVisibleEmojis ? mVisibleEmojis - 1 : 0;
|
||||
}
|
||||
}
|
||||
else if (cntEmoji - 1 == mCurSelected)
|
||||
{
|
||||
|
|
@ -273,11 +292,11 @@ BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_pare
|
|||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (handled)
|
||||
return TRUE;
|
||||
|
||||
return LLFloater::handleKey(key, mask, called_from_parent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
|
||||
{
|
||||
Optional<bool> autosize;
|
||||
Optional<bool> noscroll;
|
||||
Optional<S32> max_emoji,
|
||||
padding;
|
||||
|
||||
|
|
@ -50,6 +51,7 @@ public:
|
|||
|
||||
protected:
|
||||
LLPanelEmojiComplete(const LLPanelEmojiComplete::Params&);
|
||||
|
||||
public:
|
||||
virtual ~LLPanelEmojiComplete();
|
||||
|
||||
|
|
@ -62,9 +64,13 @@ public:
|
|||
void reshape(S32 width, S32 height, BOOL called_from_parent) override;
|
||||
|
||||
public:
|
||||
const LLWString& getEmojis() const { return mEmojis; }
|
||||
size_t getEmojiCount() const { return mEmojis.size(); }
|
||||
void setEmojiHint(const std::string& hint);
|
||||
void setEmojis(const LLWString& emojis);
|
||||
void setEmojiHint(const std::string& hint);
|
||||
|
||||
protected:
|
||||
void LLPanelEmojiComplete::onEmojisChanged();
|
||||
size_t posToIndex(S32 x, S32 y) const;
|
||||
void select(size_t emoji_idx);
|
||||
void selectNext();
|
||||
|
|
@ -76,13 +82,14 @@ protected:
|
|||
protected:
|
||||
static constexpr auto npos = std::numeric_limits<size_t>::max();
|
||||
|
||||
bool mAutoSize = false;
|
||||
const bool mAutoSize = false;
|
||||
const bool mNoScroll = false;
|
||||
const LLFontGL* mFont;
|
||||
U16 mEmojiWidth = 0;
|
||||
size_t mMaxVisible = 0;
|
||||
S32 mPadding = 8;
|
||||
const size_t mMaxVisible = 0;
|
||||
const S32 mPadding = 8;
|
||||
LLRect mRenderRect;
|
||||
LLUIImagePtr mSelectedImage;
|
||||
const LLUIImagePtr mSelectedImage;
|
||||
|
||||
LLWString mEmojis;
|
||||
size_t mVisibleEmojis = 0;
|
||||
|
|
|
|||
|
|
@ -66,13 +66,19 @@
|
|||
<layout_panel name="chat_layout_panel">
|
||||
<layout_stack name="input_panels">
|
||||
<layout_panel name="emoji_button_layout_panel">
|
||||
<button name="emoji_panel_btn" tool_tip="Emoji-Auswahl öffnen/schliessen"/>
|
||||
<button name="emoji_picker_toggle_btn" tool_tip="Emoji-Auswahl öffnen/schliessen"/>
|
||||
<button name="emoji_recent_panel_toggle_btn" tool_tip="Zuletzt verwendete Emoji-Auswahl öffnen/schliessen"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="input_button_layout_panel">
|
||||
<button name="send_chat" label="Senden"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel name="emoji_recent_layout_panel">
|
||||
<text name="emoji_recent_empty_text">
|
||||
Zuletzt verwendete Emojis erscheinen hier
|
||||
</text>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
<chat_editor name="chat_box"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="emoji_button_layout_panel">
|
||||
<button name="emoji_panel_btn" tool_tip="Emoji-Auswahl öffnen/schliessen"/>
|
||||
<button name="emoji_picker_toggle_btn" tool_tip="Emoji-Auswahl öffnen/schliessen"/>
|
||||
<button name="emoji_recent_panel_toggle_btn" tool_tip="Zuletzt verwendete Emoji-Auswahl öffnen/schliessen"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="input_button_layout_panel">
|
||||
<spinner name="ChatChannel" tool_tip="Kanal, an den der Chat gesendet werden soll. Kann unter Einstellungen -> Chat -> Firestorm -> Kanalauswahl in Eingabezeile anzeigen aktiviert werden." label_width="35"/>
|
||||
|
|
@ -46,6 +47,11 @@
|
|||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel name="emoji_recent_layout_panel">
|
||||
<text name="emoji_recent_empty_text">
|
||||
Zuletzt verwendete Emojis erscheinen hier
|
||||
</text>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
|
|
|||
|
|
@ -12,19 +12,14 @@
|
|||
width="250">
|
||||
<floater.string name="title_for_recently_used" value="Recently used"/>
|
||||
<floater.string name="title_for_frequently_used" value="Frequently used"/>
|
||||
<line_editor
|
||||
<filter_editor
|
||||
name="Filter"
|
||||
label="Start typing to filter"
|
||||
layout="bottomleft"
|
||||
follows="bottom|left|right"
|
||||
text_tentative_color="TextFgTentativeColor"
|
||||
show_label_focused="true"
|
||||
max_length_bytes="63"
|
||||
text_pad_right="5"
|
||||
text_pad_left="5"
|
||||
bottom="5"
|
||||
left="10"
|
||||
height="29"
|
||||
height="23"
|
||||
width="230" />
|
||||
<scroll_container
|
||||
name="EmojiGridContainer"
|
||||
|
|
|
|||
|
|
@ -655,7 +655,7 @@
|
|||
auto_resize="false"
|
||||
user_resize="false"
|
||||
name="emoji_button_layout_panel"
|
||||
width="25"
|
||||
width="35"
|
||||
top="0"
|
||||
bottom="-1">
|
||||
<button
|
||||
|
|
@ -667,10 +667,25 @@
|
|||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
right="-1"
|
||||
name="emoji_panel_btn"
|
||||
right="-11"
|
||||
name="emoji_picker_toggle_btn"
|
||||
tool_tip="Show/hide emoji panel"
|
||||
width="24"/>
|
||||
<button
|
||||
follows="right|bottom"
|
||||
bottom="23"
|
||||
height="22"
|
||||
use_font_color="true"
|
||||
font="EmojiLarge"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
image_overlay="Arrow_Down"
|
||||
right="-1"
|
||||
name="emoji_recent_panel_toggle_btn"
|
||||
tool_tip="Shows/hides recent emojis"
|
||||
left_pad="0"
|
||||
width="10"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
visibility_control="FSShowIMSendButton"
|
||||
|
|
@ -693,6 +708,33 @@
|
|||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
name="emoji_recent_layout_panel"
|
||||
height="28"
|
||||
auto_resize="false">
|
||||
<text
|
||||
name="emoji_recent_empty_text"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
auto_resize="false"
|
||||
h_pad="20"
|
||||
v_pad="5"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-1"
|
||||
height="25"
|
||||
>Recently used emojis will appear here</text>
|
||||
<emoji_complete
|
||||
name="emoji_recent_icons_ctrl"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
noscroll="true"
|
||||
max_emoji="20"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-1"
|
||||
height="25"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@
|
|||
auto_resize="false"
|
||||
user_resize="false"
|
||||
name="emoji_button_layout_panel"
|
||||
width="25">
|
||||
width="35">
|
||||
<button
|
||||
follows="right|bottom"
|
||||
bottom="-1"
|
||||
|
|
@ -286,10 +286,25 @@
|
|||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
right="-1"
|
||||
name="emoji_panel_btn"
|
||||
right="-11"
|
||||
name="emoji_picker_toggle_btn"
|
||||
tool_tip="Show/hide emoji panel"
|
||||
width="24"/>
|
||||
<button
|
||||
follows="right|bottom"
|
||||
bottom="-1"
|
||||
height="22"
|
||||
use_font_color="true"
|
||||
font="EmojiLarge"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
image_overlay="Arrow_Down"
|
||||
right="-1"
|
||||
name="emoji_recent_panel_toggle_btn"
|
||||
tool_tip="Shows/hides recent emojis"
|
||||
left_pad="0"
|
||||
width="10"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
visibility_control="FSShowChatChannel"
|
||||
|
|
@ -384,6 +399,33 @@
|
|||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
name="emoji_recent_layout_panel"
|
||||
height="28"
|
||||
auto_resize="false">
|
||||
<text
|
||||
name="emoji_recent_empty_text"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
auto_resize="false"
|
||||
h_pad="20"
|
||||
v_pad="5"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-1"
|
||||
height="25"
|
||||
>Recently used emojis will appear here</text>
|
||||
<emoji_complete
|
||||
name="emoji_recent_icons_ctrl"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
noscroll="true"
|
||||
max_emoji="20"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-1"
|
||||
height="25"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@
|
|||
height="20"
|
||||
is_expandable="true"
|
||||
text_tentative_color="TextFgTentativeColor"
|
||||
bg_writeable_color="ScriptBackground"
|
||||
name="chat_editor"
|
||||
max_length="1023"
|
||||
spellcheck="true"
|
||||
|
|
@ -300,8 +301,8 @@
|
|||
right="-30"
|
||||
wrap="true" />
|
||||
<button
|
||||
name="emoji_panel_btn"
|
||||
tool_tip="Shows/hides emoji picker"
|
||||
name="emoji_recent_panel_toggle_btn"
|
||||
tool_tip="Shows/hides recent emojis"
|
||||
follows="right|bottom"
|
||||
use_font_color="true"
|
||||
font="EmojiLarge"
|
||||
|
|
@ -332,6 +333,43 @@
|
|||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
name="emoji_recent_layout_panel"
|
||||
height="35"
|
||||
auto_resize="false">
|
||||
<text
|
||||
name="emoji_recent_empty_text"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
auto_resize="false"
|
||||
h_pad="20"
|
||||
v_pad="10"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-60"
|
||||
height="30"
|
||||
>Recently used emojis will appear here</text>
|
||||
<emoji_complete
|
||||
name="emoji_recent_icons_ctrl"
|
||||
follows="top|left|right"
|
||||
layout="topleft"
|
||||
noscroll="true"
|
||||
max_emoji="20"
|
||||
top="0"
|
||||
left="5"
|
||||
right="-60"
|
||||
height="30"/>
|
||||
<button
|
||||
name="emoji_picker_toggle_btn"
|
||||
label="More"
|
||||
tool_tip="Shows/hides emoji picker"
|
||||
follows="right|bottom"
|
||||
layout="topleft"
|
||||
bottom="-5"
|
||||
right="-5"
|
||||
height="30"
|
||||
width="60"/>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</view>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@
|
|||
#if 0
|
||||
|
||||
#ifndef LL_WINDOWS
|
||||
|
||||
typedef struct {
|
||||
void *re_pcre;
|
||||
size_t re_nsub;
|
||||
size_t re_erroffset;
|
||||
} regex_t;
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue