CHUI-119 WIP
parent
fe252836eb
commit
bba0f4f74e
|
|
@ -332,7 +332,6 @@ set(viewer_SOURCE_FILES
|
|||
llnamelistctrl.cpp
|
||||
llnavigationbar.cpp
|
||||
llnearbychat.cpp
|
||||
llnearbychatbar.cpp
|
||||
llnearbychathandler.cpp
|
||||
llnearbychatbarlistener.cpp
|
||||
llnetmap.cpp
|
||||
|
|
@ -364,7 +363,6 @@ set(viewer_SOURCE_FILES
|
|||
llpanelgroupnotices.cpp
|
||||
llpanelgrouproles.cpp
|
||||
llpanelhome.cpp
|
||||
llpanelimcontrolpanel.cpp
|
||||
llpanelland.cpp
|
||||
llpanellandaudio.cpp
|
||||
llpanellandmarkinfo.cpp
|
||||
|
|
@ -890,7 +888,6 @@ set(viewer_HEADER_FILES
|
|||
llnamelistctrl.h
|
||||
llnavigationbar.h
|
||||
llnearbychat.h
|
||||
llnearbychatbar.h
|
||||
llnearbychathandler.h
|
||||
llnearbychatbarlistener.h
|
||||
llnetmap.h
|
||||
|
|
@ -916,7 +913,6 @@ set(viewer_HEADER_FILES
|
|||
llpanelgroupnotices.h
|
||||
llpanelgrouproles.h
|
||||
llpanelhome.h
|
||||
llpanelimcontrolpanel.h
|
||||
llpanelland.h
|
||||
llpanellandaudio.h
|
||||
llpanellandmarkinfo.h
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
#include "llmorphview.h"
|
||||
#include "llmoveview.h"
|
||||
#include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llpaneltopinfobar.h"
|
||||
#include "llparcel.h"
|
||||
|
|
@ -1778,7 +1778,7 @@ void LLAgent::startTyping()
|
|||
{
|
||||
sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);
|
||||
}
|
||||
LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
|
||||
LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1790,7 +1790,7 @@ void LLAgent::stopTyping()
|
|||
{
|
||||
clearRenderState(AGENT_STATE_TYPING);
|
||||
sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP);
|
||||
LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
|
||||
LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include "llfloaterreg.h"
|
||||
#include "lllocalcliprect.h"
|
||||
#include "lltrans.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
|
||||
#include "llviewercontrol.h"
|
||||
#include "llagentdata.h"
|
||||
|
|
@ -316,12 +316,12 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask)
|
|||
return TRUE;
|
||||
else
|
||||
{
|
||||
LLNearbyChatBar::getInstance()->showHistory();
|
||||
LLNearbyChat::getInstance()->showHistory();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
LLNearbyChatBar::getInstance()->showHistory();
|
||||
LLNearbyChat::getInstance()->showHistory();
|
||||
return LLPanel::handleMouseUp(x,y,mask);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "llfloatertranslationsettings.h"
|
||||
|
||||
// Viewer includes
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "lltranslate.h"
|
||||
#include "llviewercontrol.h" // for gSavedSettings
|
||||
|
||||
|
|
@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()
|
|||
gSavedSettings.setString("TranslationService", getSelectedService());
|
||||
gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());
|
||||
gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey());
|
||||
LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());
|
||||
LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());
|
||||
closeFloater(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
#include "llviewermessage.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llappearancemgr.h"
|
||||
#include "llgesturelistener.h"
|
||||
|
||||
|
|
@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)
|
|||
|
||||
const BOOL animate = FALSE;
|
||||
|
||||
LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
|
||||
LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
|
||||
|
||||
gesture->mCurrentStep++;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -27,25 +27,27 @@
|
|||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llpanelimcontrolpanel.h"
|
||||
#include "llimconversation.h"
|
||||
|
||||
#include "lldraghandle.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llimconversation.h"
|
||||
#include "llimfloater.h"
|
||||
#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container
|
||||
#include "lllayoutstack.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
|
||||
const F32 REFRESH_INTERVAL = 0.2;
|
||||
|
||||
LLIMConversation::LLIMConversation(const LLUUID& session_id)
|
||||
: LLTransientDockableFloater(NULL, true, session_id)
|
||||
, mControlPanel(NULL)
|
||||
, LLEventTimer(REFRESH_INTERVAL)
|
||||
, mIsP2PChat(false)
|
||||
, mExpandCollapseBtn(NULL)
|
||||
, mTearOffBtn(NULL)
|
||||
, mCloseBtn(NULL)
|
||||
, mSessionID(session_id)
|
||||
, mParticipantList(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("IMSession.Menu.Action",
|
||||
boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2));
|
||||
|
|
@ -63,6 +65,15 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id)
|
|||
boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2));
|
||||
}
|
||||
|
||||
LLIMConversation::~LLIMConversation()
|
||||
{
|
||||
if (mParticipantList)
|
||||
{
|
||||
delete mParticipantList;
|
||||
mParticipantList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLIMConversation::postBuild()
|
||||
{
|
||||
mCloseBtn = getChild<LLButton>("close_btn");
|
||||
|
|
@ -71,19 +82,12 @@ BOOL LLIMConversation::postBuild()
|
|||
mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
|
||||
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this));
|
||||
|
||||
if (mControlPanel)
|
||||
{
|
||||
mControlPanel->setSessionId(mSessionID);
|
||||
mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel"));
|
||||
|
||||
mExpandCollapseBtn->setImageOverlay(
|
||||
getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mExpandCollapseBtn->setEnabled(false);
|
||||
getChild<LLLayoutPanel>("im_control_panel_holder")->setVisible(false);
|
||||
}
|
||||
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
|
||||
mParticipantListPanel->setVisible(
|
||||
mIsNearbyChat? false : gSavedSettings.getBOOL("IMShowControlPanel"));
|
||||
mExpandCollapseBtn->setImageOverlay(
|
||||
getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon"));
|
||||
mExpandCollapseBtn->setEnabled(!mIsP2PChat);
|
||||
|
||||
mTearOffBtn = getChild<LLButton>("tear_off_btn");
|
||||
mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this));
|
||||
|
|
@ -93,6 +97,8 @@ BOOL LLIMConversation::postBuild()
|
|||
setOpenPositioning(LLFloaterEnums::OPEN_POSITIONING_NONE);
|
||||
}
|
||||
|
||||
buildParticipantList();
|
||||
|
||||
if (isChatMultiTab())
|
||||
{
|
||||
return LLFloater::postBuild();
|
||||
|
|
@ -104,6 +110,47 @@ BOOL LLIMConversation::postBuild()
|
|||
|
||||
}
|
||||
|
||||
BOOL LLIMConversation::tick()
|
||||
{
|
||||
// Need to resort the participant list if it's in sort by recent speaker order.
|
||||
if (mParticipantList)
|
||||
{
|
||||
mParticipantList->update();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLIMConversation::buildParticipantList()
|
||||
{ if (mIsNearbyChat)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
// for group and Ad-hoc chat we need to include agent into list
|
||||
if(!mIsP2PChat && !mParticipantList && mSessionID.notNull())
|
||||
{
|
||||
LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
|
||||
mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata)
|
||||
{
|
||||
// TODO: Check this code when when sort order menu will be added. (EM)
|
||||
if (true || !mParticipantList)
|
||||
return;
|
||||
|
||||
std::string chosen_item = userdata.asString();
|
||||
|
||||
if (chosen_item == "sort_name")
|
||||
{
|
||||
mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata)
|
||||
{
|
||||
std::string item = userdata.asString();
|
||||
|
|
@ -162,11 +209,11 @@ void LLIMConversation::updateHeaderAndToolbar()
|
|||
}
|
||||
|
||||
bool is_control_panel_visible = false;
|
||||
if (mControlPanel)
|
||||
if (!mIsP2PChat)
|
||||
{
|
||||
// Control panel should be visible only in torn off floaters.
|
||||
is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel");
|
||||
mControlPanel->getParent()->setVisible(is_control_panel_visible);
|
||||
mParticipantListPanel->setVisible(is_control_panel_visible);
|
||||
}
|
||||
|
||||
// Display collapse image (<<) if the floater is hosted
|
||||
|
|
@ -215,10 +262,10 @@ void LLIMConversation::processChatHistoryStyleUpdate()
|
|||
}
|
||||
}
|
||||
|
||||
LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance();
|
||||
if (nearby_chat_bar)
|
||||
LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
|
||||
if (nearby_chat)
|
||||
{
|
||||
nearby_chat_bar->reloadMessages();
|
||||
nearby_chat->reloadMessages();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -240,12 +287,12 @@ void LLIMConversation::onSlide(LLIMConversation* self)
|
|||
}
|
||||
else ///< floater is torn off
|
||||
{
|
||||
if (self->mControlPanel)
|
||||
if (!self->mIsP2PChat)
|
||||
{
|
||||
bool expand = !self->mControlPanel->getParent()->getVisible();
|
||||
bool expand = !self->mParticipantListPanel->getVisible();
|
||||
|
||||
// Expand/collapse the IM control panel
|
||||
self->mControlPanel->getParent()->setVisible(expand);
|
||||
self->mParticipantListPanel->setVisible(expand);
|
||||
|
||||
gSavedSettings.setBOOL("IMShowControlPanel", expand);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,19 +28,24 @@
|
|||
#ifndef LL_IMCONVERSATION_H
|
||||
#define LL_IMCONVERSATION_H
|
||||
|
||||
#include "lllayoutstack.h"
|
||||
#include "llparticipantlist.h"
|
||||
#include "lltransientdockablefloater.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
class LLPanelChatControlPanel;
|
||||
|
||||
class LLIMConversation
|
||||
: public LLTransientDockableFloater
|
||||
, public LLEventTimer
|
||||
{
|
||||
|
||||
public:
|
||||
LOG_CLASS(LLIMConversation);
|
||||
|
||||
LLIMConversation(const LLUUID& session_id);
|
||||
~LLIMConversation();
|
||||
|
||||
// reload all message with new settings of visual modes
|
||||
static void processChatHistoryStyleUpdate();
|
||||
|
|
@ -75,13 +80,16 @@ protected:
|
|||
// set the enable/disable state for the Call button
|
||||
virtual void enableDisableCallBtn() = 0;
|
||||
|
||||
// /* virtual */ void updateTitleButtons();
|
||||
void buildParticipantList();
|
||||
void onSortMenuItemClicked(const LLSD& userdata);
|
||||
|
||||
/*virtual*/ BOOL tick();
|
||||
|
||||
LLPanelChatControlPanel* mControlPanel;
|
||||
bool mIsNearbyChat;
|
||||
bool mIsP2PChat;
|
||||
|
||||
LLLayoutPanel* mParticipantListPanel;
|
||||
LLParticipantList* mParticipantList;
|
||||
LLUUID mSessionID;
|
||||
|
||||
LLButton* mExpandCollapseBtn;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
//#include "lllayoutstack.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "lllogchat.h"
|
||||
#include "llpanelimcontrolpanel.h"
|
||||
#include "llscreenchannel.h"
|
||||
#include "llsyswellwindow.h"
|
||||
#include "lltrans.h"
|
||||
|
|
@ -82,29 +81,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
|
|||
{
|
||||
mIsP2PChat = mSession->isP2PSessionType();
|
||||
mSessionInitialized = mSession->mSessionInitialized;
|
||||
|
||||
mDialog = mSession->mType;
|
||||
switch (mDialog)
|
||||
{
|
||||
case IM_SESSION_CONFERENCE_START:
|
||||
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
|
||||
break;
|
||||
case IM_SESSION_GROUP_START:
|
||||
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
|
||||
break;
|
||||
case IM_SESSION_INVITE:
|
||||
if (gAgent.isInGroup(mSessionID))
|
||||
{
|
||||
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
setOverlapsScreenChannel(true);
|
||||
|
||||
|
|
@ -113,24 +90,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
|
|||
setDocked(true);
|
||||
}
|
||||
|
||||
// static
|
||||
void* LLIMFloater::createPanelGroupControl(void* userdata)
|
||||
{
|
||||
LLIMFloater *self = (LLIMFloater*) userdata;
|
||||
self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID);
|
||||
self->mControlPanel->setXMLFilename("panel_group_control_panel.xml");
|
||||
return self->mControlPanel;
|
||||
}
|
||||
|
||||
// static
|
||||
void* LLIMFloater::createPanelAdHocControl(void* userdata)
|
||||
{
|
||||
LLIMFloater *self = (LLIMFloater*) userdata;
|
||||
self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
|
||||
self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
|
||||
return self->mControlPanel;
|
||||
}
|
||||
|
||||
void LLIMFloater::onFocusLost()
|
||||
{
|
||||
LLIMModel::getInstance()->resetActiveSessionID();
|
||||
|
|
@ -409,8 +368,10 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
|
|||
}
|
||||
|
||||
// virtual
|
||||
void LLIMFloater::draw()
|
||||
BOOL LLIMFloater::tick()
|
||||
{
|
||||
BOOL parents_retcode = LLIMConversation::tick();
|
||||
|
||||
if ( mMeTyping )
|
||||
{
|
||||
// Time out if user hasn't typed for a while.
|
||||
|
|
@ -420,7 +381,7 @@ void LLIMFloater::draw()
|
|||
}
|
||||
}
|
||||
|
||||
LLTransientDockableFloater::draw();
|
||||
return parents_retcode;
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -643,16 +604,14 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
|
|||
if (mSessionID != im_session_id)
|
||||
{
|
||||
mSessionID = im_session_id;
|
||||
|
||||
setKey(im_session_id);
|
||||
if (mControlPanel)
|
||||
{
|
||||
mControlPanel->setSessionId(im_session_id);
|
||||
}
|
||||
|
||||
boundVoiceChannel();
|
||||
|
||||
mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
|
||||
mIsP2PChat = mSession && mSession->isP2PSessionType();
|
||||
|
||||
buildParticipantList();
|
||||
}
|
||||
|
||||
//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
|
||||
|
|
@ -841,10 +800,14 @@ void LLIMFloater::setTyping(bool typing)
|
|||
}
|
||||
}
|
||||
|
||||
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
|
||||
if (speaker_mgr)
|
||||
speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
|
||||
|
||||
if (!mIsNearbyChat)
|
||||
{
|
||||
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
|
||||
if (speaker_mgr)
|
||||
{
|
||||
speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
|
||||
|
|
|
|||
|
|
@ -61,15 +61,15 @@ public:
|
|||
/*virtual*/ void setVisible(BOOL visible);
|
||||
/*virtual*/ BOOL getVisible();
|
||||
// Check typing timeout timer.
|
||||
/*virtual*/ void draw();
|
||||
|
||||
static void* createPanelGroupControl(void* userdata);
|
||||
static void* createPanelAdHocControl(void* userdata);
|
||||
/*virtual*/ BOOL tick();
|
||||
|
||||
static LLIMFloater* findInstance(const LLUUID& session_id);
|
||||
static LLIMFloater* getInstance(const LLUUID& session_id);
|
||||
static void addToHost(const LLUUID& session_id);
|
||||
|
||||
static void* createPanelGroupControl(void* userdata);
|
||||
static void* createPanelAdHocControl(void* userdata);
|
||||
|
||||
// LLFloater overrides
|
||||
/*virtual*/ void onClose(bool app_quitting);
|
||||
/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
|
||||
|
|
@ -147,7 +147,6 @@ private:
|
|||
static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
|
||||
static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
|
||||
void setTyping(bool typing);
|
||||
|
||||
void onCallButtonClicked();
|
||||
|
||||
// set the enable/disable state for the Call button
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "llfloaterreg.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llavatariconctrl.h"
|
||||
|
|
|
|||
|
|
@ -907,7 +907,7 @@ const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const
|
|||
LLIMSession* session = findIMSession(session_id);
|
||||
if (!session)
|
||||
{
|
||||
llwarns << "session " << session_id << "does not exist " << llendl;
|
||||
llwarns << "session " << session_id << " does not exist " << llendl;
|
||||
return LLUUID::null;
|
||||
}
|
||||
|
||||
|
|
@ -2483,8 +2483,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
|
|||
LLChat chat(message);
|
||||
chat.mSourceType = CHAT_SOURCE_SYSTEM;
|
||||
|
||||
LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar");
|
||||
LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat");
|
||||
LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
|
||||
|
||||
if(nearby_chat)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* @file LLNearbyChat.cpp
|
||||
* @brief Nearby chat history scrolling panel implementation
|
||||
* @brief LLNearbyChat class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
|
|
@ -25,34 +25,50 @@
|
|||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llrootview.h"
|
||||
//#include "llchatitemscontainerctrl.h"
|
||||
|
||||
#include "message.h"
|
||||
|
||||
#include "lliconctrl.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lltrans.h"
|
||||
#include "llimfloatercontainer.h"
|
||||
#include "llfloatersidepanelcontainer.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "lllogchat.h"
|
||||
#include "llresizebar.h"
|
||||
#include "llresizehandle.h"
|
||||
#include "lldraghandle.h"
|
||||
#include "llmenugl.h"
|
||||
#include "llviewermenu.h"//for gMenuHolder
|
||||
|
||||
#include "llviewermenu.h" // for gMenuHolder
|
||||
#include "llnearbychathandler.h"
|
||||
#include "llchannelmanager.h"
|
||||
|
||||
#include "llagent.h" // gAgent
|
||||
#include "llchathistory.h"
|
||||
#include "llstylemap.h"
|
||||
|
||||
#include "llavatarnamecache.h"
|
||||
|
||||
#include "lldraghandle.h"
|
||||
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
#include "llfirstuse.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llagent.h" // gAgent
|
||||
#include "llgesturemgr.h"
|
||||
#include "llmultigesture.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "llanimationstates.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llnavigationbar.h"
|
||||
#include "llwindow.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llrootview.h"
|
||||
#include "llviewerchat.h"
|
||||
#include "lltranslate.h"
|
||||
|
||||
S32 LLNearbyChat::sLastSpecialChatChannel = 0;
|
||||
|
||||
|
||||
// --- 2 functions in the global namespace :( ---
|
||||
bool isWordsName(const std::string& name)
|
||||
{
|
||||
|
|
@ -88,35 +104,531 @@ std::string appendTime()
|
|||
return timeStr;
|
||||
}
|
||||
|
||||
static const S32 RESIZE_BAR_THICKNESS = 3;
|
||||
|
||||
static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat");
|
||||
const S32 EXPANDED_HEIGHT = 266;
|
||||
const S32 COLLAPSED_HEIGHT = 60;
|
||||
const S32 EXPANDED_MIN_HEIGHT = 150;
|
||||
|
||||
LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p)
|
||||
: LLPanel(p),
|
||||
mChatHistory(NULL)
|
||||
// legacy callback glue
|
||||
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
|
||||
|
||||
struct LLChatTypeTrigger {
|
||||
std::string name;
|
||||
EChatType type;
|
||||
};
|
||||
|
||||
static LLChatTypeTrigger sChatTypeTriggers[] = {
|
||||
{ "/whisper" , CHAT_TYPE_WHISPER},
|
||||
{ "/shout" , CHAT_TYPE_SHOUT}
|
||||
};
|
||||
|
||||
|
||||
LLNearbyChat::LLNearbyChat(const LLSD& key)
|
||||
: LLIMConversation(key),
|
||||
mChatBox(NULL),
|
||||
mChatHistory(NULL),
|
||||
mOutputMonitor(NULL),
|
||||
mSpeakerMgr(NULL),
|
||||
mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)
|
||||
{
|
||||
mSpeakerMgr = LLLocalSpeakerMgr::getInstance();
|
||||
}
|
||||
|
||||
//virtual
|
||||
BOOL LLNearbyChat::postBuild()
|
||||
{
|
||||
//menu
|
||||
mChatBox = getChild<LLLineEditor>("chat_editor");
|
||||
|
||||
mChatBox->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this));
|
||||
mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this);
|
||||
mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this));
|
||||
mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this));
|
||||
mChatBox->setIgnoreArrowKeys( FALSE );
|
||||
mChatBox->setCommitOnFocusLost( FALSE );
|
||||
mChatBox->setRevertOnEsc( FALSE );
|
||||
mChatBox->setIgnoreTab(TRUE);
|
||||
mChatBox->setPassDelete(TRUE);
|
||||
mChatBox->setReplaceNewlinesWithSpaces(FALSE);
|
||||
mChatBox->setEnableLineHistory(TRUE);
|
||||
mChatBox->setFont(LLViewerChat::getChatFont());
|
||||
|
||||
mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
|
||||
mOutputMonitor->setVisible(FALSE);
|
||||
|
||||
// Register for font change notifications
|
||||
LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1));
|
||||
|
||||
enableResizeCtrls(true, true, false);
|
||||
|
||||
addToHost();
|
||||
|
||||
//for menu
|
||||
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
|
||||
enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2));
|
||||
registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2));
|
||||
|
||||
|
||||
LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
|
||||
if(menu)
|
||||
{
|
||||
mPopupMenuHandle = menu->getHandle();
|
||||
}
|
||||
|
||||
gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true);
|
||||
// obsolete, but may be needed for backward compatibility?
|
||||
gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true);
|
||||
|
||||
mChatHistory = getChild<LLChatHistory>("chat_history");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
return LLIMConversation::postBuild();;
|
||||
}
|
||||
|
||||
void LLNearbyChat::onNearbySpeakers()
|
||||
{
|
||||
LLSD param;
|
||||
param["people_panel_tab_name"] = "nearby_panel";
|
||||
LLFloaterSidePanelContainer::showPanel("people", "panel_people", param);
|
||||
}
|
||||
|
||||
void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)
|
||||
{
|
||||
}
|
||||
|
||||
bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)
|
||||
{
|
||||
std::string str = userdata.asString();
|
||||
if(str == "nearby_people")
|
||||
onNearbySpeakers();
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLNearbyChat::getAllowedRect(LLRect& rect)
|
||||
{
|
||||
rect = gViewerWindow->getWorldViewRectScaled();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLNearbyChat::onFocusReceived()
|
||||
{
|
||||
setBackgroundOpaque(true);
|
||||
LLIMConversation::onFocusReceived();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLNearbyChat::onFocusLost()
|
||||
{
|
||||
setBackgroundOpaque(false);
|
||||
LLIMConversation::onFocusLost();
|
||||
}
|
||||
|
||||
BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
//fix for EXT-6625
|
||||
//highlight NearbyChat history whenever mouseclick happen in NearbyChat
|
||||
//setting focus to eidtor will force onFocusLost() call that in its turn will change
|
||||
//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change.
|
||||
|
||||
if(mChatHistory)
|
||||
mChatHistory->setFocus(TRUE);
|
||||
return LLPanel::handleMouseDown(x, y, mask);
|
||||
}
|
||||
|
||||
void LLNearbyChat::reloadMessages()
|
||||
{
|
||||
mChatHistory->clear();
|
||||
|
||||
LLSD do_not_log;
|
||||
do_not_log["do_not_log"] = true;
|
||||
for(std::vector<LLChat>::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it)
|
||||
{
|
||||
// Update the messages without re-writing them to a log file.
|
||||
addMessage(*it,false, do_not_log);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::loadHistory()
|
||||
{
|
||||
LLSD do_not_log;
|
||||
do_not_log["do_not_log"] = true;
|
||||
|
||||
std::list<LLSD> history;
|
||||
LLLogChat::loadAllHistory("chat", history);
|
||||
|
||||
std::list<LLSD>::const_iterator it = history.begin();
|
||||
while (it != history.end())
|
||||
{
|
||||
const LLSD& msg = *it;
|
||||
|
||||
std::string from = msg[IM_FROM];
|
||||
LLUUID from_id;
|
||||
if (msg[IM_FROM_ID].isDefined())
|
||||
{
|
||||
from_id = msg[IM_FROM_ID].asUUID();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string legacy_name = gCacheName->buildLegacyName(from);
|
||||
gCacheName->getUUID(legacy_name, from_id);
|
||||
}
|
||||
|
||||
LLChat chat;
|
||||
chat.mFromName = from;
|
||||
chat.mFromID = from_id;
|
||||
chat.mText = msg[IM_TEXT].asString();
|
||||
chat.mTimeStr = msg[IM_TIME].asString();
|
||||
chat.mChatStyle = CHAT_STYLE_HISTORY;
|
||||
|
||||
chat.mSourceType = CHAT_SOURCE_AGENT;
|
||||
if (from_id.isNull() && SYSTEM_FROM == from)
|
||||
{
|
||||
chat.mSourceType = CHAT_SOURCE_SYSTEM;
|
||||
|
||||
}
|
||||
else if (from_id.isNull())
|
||||
{
|
||||
chat.mSourceType = isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
|
||||
}
|
||||
|
||||
addMessage(chat, true, do_not_log);
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::removeScreenChat()
|
||||
{
|
||||
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
|
||||
if(chat_channel)
|
||||
{
|
||||
chat_channel->removeToastsFromChannel();
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::setVisible(BOOL visible)
|
||||
{
|
||||
if(visible)
|
||||
{
|
||||
removeScreenChat();
|
||||
}
|
||||
|
||||
LLIMConversation::setVisible(visible);
|
||||
}
|
||||
|
||||
void LLNearbyChat::onCallButtonClicked()
|
||||
{
|
||||
LLAgent::toggleMicrophone(NULL);
|
||||
}
|
||||
|
||||
void LLNearbyChat::enableDisableCallBtn()
|
||||
{
|
||||
// bool btn_enabled = LLAgent::isActionAllowed("speak");
|
||||
|
||||
getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/);
|
||||
}
|
||||
|
||||
void LLNearbyChat::addToHost()
|
||||
{
|
||||
if (LLIMConversation::isChatMultiTab())
|
||||
{
|
||||
LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance();
|
||||
|
||||
if (im_box)
|
||||
{
|
||||
im_box->addFloater(this, FALSE, LLTabContainer::END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLNearbyChat::onOpen(const LLSD& key)
|
||||
{
|
||||
LLIMConversation::onOpen(key);
|
||||
showTranslationCheckbox(LLTranslate::isTranslationConfigured());
|
||||
}
|
||||
|
||||
bool LLNearbyChat::applyRectControl()
|
||||
{
|
||||
bool rect_controlled = LLFloater::applyRectControl();
|
||||
|
||||
/* if (!mNearbyChat->getVisible())
|
||||
{
|
||||
reshape(getRect().getWidth(), getMinHeight());
|
||||
enableResizeCtrls(true, true, false);
|
||||
}
|
||||
else
|
||||
{*/
|
||||
enableResizeCtrls(true);
|
||||
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
|
||||
// }
|
||||
|
||||
return rect_controlled;
|
||||
}
|
||||
|
||||
void LLNearbyChat::onChatFontChange(LLFontGL* fontp)
|
||||
{
|
||||
// Update things with the new font whohoo
|
||||
if (mChatBox)
|
||||
{
|
||||
mChatBox->setFont(fontp);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLNearbyChat* LLNearbyChat::getInstance()
|
||||
{
|
||||
return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar");
|
||||
}
|
||||
|
||||
//static
|
||||
//LLNearbyChat* LLNearbyChat::findInstance()
|
||||
//{
|
||||
// return LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar");
|
||||
//}
|
||||
|
||||
void LLNearbyChat::showHistory()
|
||||
{
|
||||
openFloater();
|
||||
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
|
||||
reshape(getRect().getWidth(), mExpandedHeight);
|
||||
enableResizeCtrls(true);
|
||||
storeRectControl();
|
||||
}
|
||||
|
||||
void LLNearbyChat::showTranslationCheckbox(BOOL show)
|
||||
{
|
||||
getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show);
|
||||
}
|
||||
|
||||
BOOL LLNearbyChat::tick()
|
||||
{
|
||||
BOOL parents_retcode = LLIMConversation::tick();
|
||||
|
||||
displaySpeakingIndicator();
|
||||
updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState());
|
||||
|
||||
// *HACK: Update transparency type depending on whether our children have focus.
|
||||
// This is needed because this floater is chrome and thus cannot accept focus, so
|
||||
// the transparency type setting code from LLFloater::setFocus() isn't reached.
|
||||
if (getTransparencyType() != TT_DEFAULT)
|
||||
{
|
||||
setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);
|
||||
}
|
||||
|
||||
return parents_retcode;
|
||||
}
|
||||
|
||||
std::string LLNearbyChat::getCurrentChat()
|
||||
{
|
||||
return mChatBox ? mChatBox->getText() : LLStringUtil::null;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask )
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
|
||||
if( KEY_RETURN == key && mask == MASK_CONTROL)
|
||||
{
|
||||
// shout
|
||||
sendChat(CHAT_TYPE_SHOUT);
|
||||
handled = TRUE;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str)
|
||||
{
|
||||
U32 in_len = in_str.length();
|
||||
S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers);
|
||||
|
||||
bool string_was_found = false;
|
||||
|
||||
for (S32 n = 0; n < cnt && !string_was_found; n++)
|
||||
{
|
||||
if (in_len <= sChatTypeTriggers[n].name.length())
|
||||
{
|
||||
std::string trigger_trunc = sChatTypeTriggers[n].name;
|
||||
LLStringUtil::truncate(trigger_trunc, in_len);
|
||||
|
||||
if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc))
|
||||
{
|
||||
*out_str = sChatTypeTriggers[n].name;
|
||||
string_was_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string_was_found;
|
||||
}
|
||||
|
||||
void LLNearbyChat::onChatBoxKeystroke(LLLineEditor* caller, void* userdata)
|
||||
{
|
||||
LLFirstUse::otherAvatarChatFirst(false);
|
||||
|
||||
LLNearbyChat* self = (LLNearbyChat *)userdata;
|
||||
|
||||
LLWString raw_text = self->mChatBox->getWText();
|
||||
|
||||
// Can't trim the end, because that will cause autocompletion
|
||||
// to eat trailing spaces that might be part of a gesture.
|
||||
LLWStringUtil::trimHead(raw_text);
|
||||
|
||||
S32 length = raw_text.length();
|
||||
|
||||
if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences
|
||||
{
|
||||
gAgent.startTyping();
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
|
||||
/* Doesn't work -- can't tell the difference between a backspace
|
||||
that killed the selection vs. backspace at the end of line.
|
||||
if (length > 1
|
||||
&& text[0] == '/'
|
||||
&& key == KEY_BACKSPACE)
|
||||
{
|
||||
// the selection will already be deleted, but we need to trim
|
||||
// off the character before
|
||||
std::string new_text = raw_text.substr(0, length-1);
|
||||
self->mInputEditor->setText( new_text );
|
||||
self->mInputEditor->setCursorToEnd();
|
||||
length = length - 1;
|
||||
}
|
||||
*/
|
||||
|
||||
KEY key = gKeyboard->currentKey();
|
||||
|
||||
// Ignore "special" keys, like backspace, arrows, etc.
|
||||
if (length > 1
|
||||
&& raw_text[0] == '/'
|
||||
&& key < KEY_SPECIAL)
|
||||
{
|
||||
// we're starting a gesture, attempt to autocomplete
|
||||
|
||||
std::string utf8_trigger = wstring_to_utf8str(raw_text);
|
||||
std::string utf8_out_str(utf8_trigger);
|
||||
|
||||
if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
|
||||
S32 outlength = self->mChatBox->getLength(); // in characters
|
||||
|
||||
// Select to end of line, starting from the character
|
||||
// after the last one the user typed.
|
||||
self->mChatBox->setSelection(length, outlength);
|
||||
}
|
||||
else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part
|
||||
self->mChatBox->setCursorToEnd();
|
||||
}
|
||||
|
||||
//llinfos << "GESTUREDEBUG " << trigger
|
||||
// << " len " << length
|
||||
// << " outlen " << out_str.getLength()
|
||||
// << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata)
|
||||
{
|
||||
// stop typing animation
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
|
||||
void LLNearbyChat::onChatBoxFocusReceived()
|
||||
{
|
||||
mChatBox->setEnabled(!gDisconnected);
|
||||
}
|
||||
|
||||
EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str)
|
||||
{
|
||||
U32 length = str.length();
|
||||
S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers);
|
||||
|
||||
for (S32 n = 0; n < cnt; n++)
|
||||
{
|
||||
if (length >= sChatTypeTriggers[n].name.length())
|
||||
{
|
||||
std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length());
|
||||
|
||||
if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name))
|
||||
{
|
||||
U32 trigger_length = sChatTypeTriggers[n].name.length();
|
||||
|
||||
// It's to remove space after trigger name
|
||||
if (length > trigger_length && str[trigger_length] == ' ')
|
||||
trigger_length++;
|
||||
|
||||
str = str.substr(trigger_length, length);
|
||||
|
||||
if (CHAT_TYPE_NORMAL == type)
|
||||
return sChatTypeTriggers[n].type;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void LLNearbyChat::sendChat( EChatType type )
|
||||
{
|
||||
if (mChatBox)
|
||||
{
|
||||
LLWString text = mChatBox->getConvertedText();
|
||||
if (!text.empty())
|
||||
{
|
||||
// store sent line in history, duplicates will get filtered
|
||||
mChatBox->updateHistory();
|
||||
// Check if this is destined for another channel
|
||||
S32 channel = 0;
|
||||
stripChannelNumber(text, &channel);
|
||||
|
||||
std::string utf8text = wstring_to_utf8str(text);
|
||||
// Try to trigger a gesture, if not chat to a script.
|
||||
std::string utf8_revised_text;
|
||||
if (0 == channel)
|
||||
{
|
||||
// discard returned "found" boolean
|
||||
LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_revised_text = utf8text;
|
||||
}
|
||||
|
||||
utf8_revised_text = utf8str_trim(utf8_revised_text);
|
||||
|
||||
type = processChatTypeTriggers(type, utf8_revised_text);
|
||||
|
||||
if (!utf8_revised_text.empty())
|
||||
{
|
||||
// Chat with animation
|
||||
sendChatFromViewer(utf8_revised_text, type, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
mChatBox->setText(LLStringExplicit(""));
|
||||
}
|
||||
|
||||
gAgent.stopTyping();
|
||||
|
||||
// If the user wants to stop chatting on hitting return, lose focus
|
||||
// and go out of chat mode.
|
||||
if (gSavedSettings.getBOOL("CloseChatOnReturn"))
|
||||
{
|
||||
stopChat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -174,156 +686,240 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
|
|||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::onNearbySpeakers()
|
||||
{
|
||||
LLSD param;
|
||||
param["people_panel_tab_name"] = "nearby_panel";
|
||||
LLFloaterSidePanelContainer::showPanel("people", "panel_people", param);
|
||||
}
|
||||
|
||||
void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)
|
||||
void LLNearbyChat::onChatBoxCommit()
|
||||
{
|
||||
}
|
||||
|
||||
bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)
|
||||
{
|
||||
std::string str = userdata.asString();
|
||||
if(str == "nearby_people")
|
||||
onNearbySpeakers();
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLNearbyChat::removeScreenChat()
|
||||
{
|
||||
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
|
||||
if(chat_channel)
|
||||
if (mChatBox->getText().length() > 0)
|
||||
{
|
||||
chat_channel->removeToastsFromChannel();
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::setVisible(BOOL visible)
|
||||
{
|
||||
if(visible)
|
||||
{
|
||||
removeScreenChat();
|
||||
sendChat(CHAT_TYPE_NORMAL);
|
||||
}
|
||||
|
||||
LLPanel::setVisible(visible);
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
|
||||
|
||||
void LLNearbyChat::getAllowedRect(LLRect& rect)
|
||||
void LLNearbyChat::displaySpeakingIndicator()
|
||||
{
|
||||
rect = gViewerWindow->getWorldViewRectScaled();
|
||||
}
|
||||
LLSpeakerMgr::speaker_list_t speaker_list;
|
||||
LLUUID id;
|
||||
|
||||
void LLNearbyChat::reloadMessages()
|
||||
{
|
||||
mChatHistory->clear();
|
||||
id.setNull();
|
||||
mSpeakerMgr->update(TRUE);
|
||||
mSpeakerMgr->getSpeakerList(&speaker_list, FALSE);
|
||||
|
||||
LLSD do_not_log;
|
||||
do_not_log["do_not_log"] = true;
|
||||
for(std::vector<LLChat>::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it)
|
||||
for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
|
||||
{
|
||||
// Update the messages without re-writing them to a log file.
|
||||
addMessage(*it,false, do_not_log);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::loadHistory()
|
||||
{
|
||||
LLSD do_not_log;
|
||||
do_not_log["do_not_log"] = true;
|
||||
|
||||
std::list<LLSD> history;
|
||||
LLLogChat::loadAllHistory("chat", history);
|
||||
|
||||
std::list<LLSD>::const_iterator it = history.begin();
|
||||
while (it != history.end())
|
||||
{
|
||||
const LLSD& msg = *it;
|
||||
|
||||
std::string from = msg[IM_FROM];
|
||||
LLUUID from_id;
|
||||
if (msg[IM_FROM_ID].isDefined())
|
||||
LLPointer<LLSpeaker> s = *i;
|
||||
if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
|
||||
{
|
||||
from_id = msg[IM_FROM_ID].asUUID();
|
||||
id = s->mID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!id.isNull())
|
||||
{
|
||||
mOutputMonitor->setVisible(TRUE);
|
||||
mOutputMonitor->setSpeakerId(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutputMonitor->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate)
|
||||
{
|
||||
sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate);
|
||||
}
|
||||
|
||||
void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
|
||||
{
|
||||
// Look for "/20 foo" channel chats.
|
||||
S32 channel = 0;
|
||||
LLWString out_text = stripChannelNumber(wtext, &channel);
|
||||
std::string utf8_out_text = wstring_to_utf8str(out_text);
|
||||
std::string utf8_text = wstring_to_utf8str(wtext);
|
||||
|
||||
utf8_text = utf8str_trim(utf8_text);
|
||||
if (!utf8_text.empty())
|
||||
{
|
||||
utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
|
||||
}
|
||||
|
||||
// Don't animate for chats people can't hear (chat to scripts)
|
||||
if (animate && (channel == 0))
|
||||
{
|
||||
if (type == CHAT_TYPE_WHISPER)
|
||||
{
|
||||
lldebugs << "You whisper " << utf8_text << llendl;
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START);
|
||||
}
|
||||
else if (type == CHAT_TYPE_NORMAL)
|
||||
{
|
||||
lldebugs << "You say " << utf8_text << llendl;
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START);
|
||||
}
|
||||
else if (type == CHAT_TYPE_SHOUT)
|
||||
{
|
||||
lldebugs << "You shout " << utf8_text << llendl;
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string legacy_name = gCacheName->buildLegacyName(from);
|
||||
gCacheName->getUUID(legacy_name, from_id);
|
||||
}
|
||||
|
||||
LLChat chat;
|
||||
chat.mFromName = from;
|
||||
chat.mFromID = from_id;
|
||||
chat.mText = msg[IM_TEXT].asString();
|
||||
chat.mTimeStr = msg[IM_TIME].asString();
|
||||
chat.mChatStyle = CHAT_STYLE_HISTORY;
|
||||
|
||||
chat.mSourceType = CHAT_SOURCE_AGENT;
|
||||
if (from_id.isNull() && SYSTEM_FROM == from)
|
||||
{
|
||||
chat.mSourceType = CHAT_SOURCE_SYSTEM;
|
||||
|
||||
}
|
||||
else if (from_id.isNull())
|
||||
{
|
||||
chat.mSourceType = isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
|
||||
llinfos << "send_chat_from_viewer() - invalid volume" << llendl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP)
|
||||
{
|
||||
lldebugs << "Channel chat: " << utf8_text << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
send_chat_from_viewer(utf8_out_text, type, channel);
|
||||
}
|
||||
|
||||
// static
|
||||
void LLNearbyChat::startChat(const char* line)
|
||||
{
|
||||
LLNearbyChat* cb = LLNearbyChat::getInstance();
|
||||
|
||||
if (cb )
|
||||
{
|
||||
cb->setVisible(TRUE);
|
||||
cb->setFocus(TRUE);
|
||||
cb->mChatBox->setFocus(TRUE);
|
||||
|
||||
if (line)
|
||||
{
|
||||
std::string line_string(line);
|
||||
cb->mChatBox->setText(line_string);
|
||||
}
|
||||
|
||||
addMessage(chat, true, do_not_log);
|
||||
|
||||
it++;
|
||||
cb->mChatBox->setCursorToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLNearbyChat* LLNearbyChat::getInstance()
|
||||
// Exit "chat mode" and do the appropriate focus changes
|
||||
// static
|
||||
void LLNearbyChat::stopChat()
|
||||
{
|
||||
LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar");
|
||||
return chat_bar->findChild<LLNearbyChat>("nearby_chat");
|
||||
}
|
||||
LLNearbyChat* cb = LLNearbyChat::getInstance();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLNearbyChat::onFocusReceived()
|
||||
{
|
||||
setBackgroundOpaque(true);
|
||||
LLPanel::onFocusReceived();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLNearbyChat::onFocusLost()
|
||||
{
|
||||
setBackgroundOpaque(false);
|
||||
LLPanel::onFocusLost();
|
||||
}
|
||||
|
||||
BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
//fix for EXT-6625
|
||||
//highlight NearbyChat history whenever mouseclick happen in NearbyChat
|
||||
//setting focus to eidtor will force onFocusLost() call that in its turn will change
|
||||
//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change.
|
||||
|
||||
if(mChatHistory)
|
||||
mChatHistory->setFocus(TRUE);
|
||||
return LLPanel::handleMouseDown(x, y, mask);
|
||||
}
|
||||
|
||||
void LLNearbyChat::draw()
|
||||
{
|
||||
// *HACK: Update transparency type depending on whether our children have focus.
|
||||
// This is needed because this floater is chrome and thus cannot accept focus, so
|
||||
// the transparency type setting code from LLFloater::setFocus() isn't reached.
|
||||
if (getTransparencyType() != TT_DEFAULT)
|
||||
if (cb)
|
||||
{
|
||||
setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);
|
||||
}
|
||||
cb->mChatBox->setFocus(FALSE);
|
||||
|
||||
LLPanel::draw();
|
||||
// stop typing animation
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
}
|
||||
|
||||
// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20.
|
||||
// Otherwise returns input and channel 0.
|
||||
LLWString LLNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel)
|
||||
{
|
||||
if (mesg[0] == '/'
|
||||
&& mesg[1] == '/')
|
||||
{
|
||||
// This is a "repeat channel send"
|
||||
*channel = sLastSpecialChatChannel;
|
||||
return mesg.substr(2, mesg.length() - 2);
|
||||
}
|
||||
else if (mesg[0] == '/'
|
||||
&& mesg[1]
|
||||
&& LLStringOps::isDigit(mesg[1]))
|
||||
{
|
||||
// This a special "/20" speak on a channel
|
||||
S32 pos = 0;
|
||||
|
||||
// Copy the channel number into a string
|
||||
LLWString channel_string;
|
||||
llwchar c;
|
||||
do
|
||||
{
|
||||
c = mesg[pos+1];
|
||||
channel_string.push_back(c);
|
||||
pos++;
|
||||
}
|
||||
while(c && pos < 64 && LLStringOps::isDigit(c));
|
||||
|
||||
// Move the pointer forward to the first non-whitespace char
|
||||
// Check isspace before looping, so we can handle "/33foo"
|
||||
// as well as "/33 foo"
|
||||
while(c && iswspace(c))
|
||||
{
|
||||
c = mesg[pos+1];
|
||||
pos++;
|
||||
}
|
||||
|
||||
sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10);
|
||||
*channel = sLastSpecialChatChannel;
|
||||
return mesg.substr(pos, mesg.length() - pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is normal chat.
|
||||
*channel = 0;
|
||||
return mesg;
|
||||
}
|
||||
}
|
||||
|
||||
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_ChatFromViewer);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_ChatData);
|
||||
msg->addStringFast(_PREHASH_Message, utf8_out_text);
|
||||
msg->addU8Fast(_PREHASH_Type, type);
|
||||
msg->addS32("Channel", channel);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
|
||||
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
|
||||
}
|
||||
|
||||
class LLChatCommandHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
// not allowed from outside the app
|
||||
LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
|
||||
|
||||
// Your code here
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
bool retval = false;
|
||||
// Need at least 2 tokens to have a valid message.
|
||||
if (tokens.size() < 2)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 channel = tokens[0].asInteger();
|
||||
// VWR-19499 Restrict function to chat channels greater than 0.
|
||||
if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG))
|
||||
{
|
||||
retval = true;
|
||||
// Send unescaped message, see EXT-6353.
|
||||
std::string unescaped_mesg (LLURI::unescape(tokens[1].asString()));
|
||||
send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = false;
|
||||
// Tell us this is an unsupported SLurl.
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
// Creating the object registers with the dispatcher.
|
||||
LLChatCommandHandler gChatHandler;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
/**
|
||||
* @file llnearbychat.h
|
||||
* @brief nearby chat history scrolling panel implementation
|
||||
* @brief LLNearbyChat class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
|
|
@ -24,9 +24,16 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLNEARBYCHAT_H_
|
||||
#define LL_LLNEARBYCHAT_H_
|
||||
#ifndef LL_LLNEARBYCHAT_H
|
||||
#define LL_LLNEARBYCHAT_H
|
||||
|
||||
#include "llimconversation.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "llchat.h"
|
||||
#include "llvoiceclient.h"
|
||||
#include "lloutputmonitorctrl.h"
|
||||
#include "llspeakers.h"
|
||||
#include "llscrollbar.h"
|
||||
#include "llviewerchat.h"
|
||||
#include "llpanel.h"
|
||||
|
|
@ -35,32 +42,88 @@ class LLResizeBar;
|
|||
class LLChatHistory;
|
||||
|
||||
class LLNearbyChat
|
||||
: public LLPanel
|
||||
: public LLIMConversation
|
||||
{
|
||||
public:
|
||||
LLNearbyChat(const Params& p = LLPanel::getDefaultParams());
|
||||
// constructor for inline chat-bars (e.g. hosted in chat history window)
|
||||
LLNearbyChat(const LLSD& key);
|
||||
~LLNearbyChat() {}
|
||||
|
||||
BOOL postBuild ();
|
||||
|
||||
/** @param archive true - to save a message to the chat history log */
|
||||
void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD());
|
||||
void onNearbyChatContextMenuItemClicked(const LLSD& userdata);
|
||||
bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
|
||||
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
virtual void draw();
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
|
||||
// focus overrides
|
||||
/*virtual*/ void onFocusLost();
|
||||
/*virtual*/ void onFocusReceived();
|
||||
|
||||
|
||||
/*virtual*/ void setVisible(BOOL visible);
|
||||
|
||||
|
||||
void loadHistory();
|
||||
void reloadMessages();
|
||||
static LLNearbyChat* getInstance();
|
||||
void removeScreenChat();
|
||||
|
||||
static LLNearbyChat* getInstance();
|
||||
|
||||
void addToHost();
|
||||
|
||||
/** @param archive true - to save a message to the chat history log */
|
||||
void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD());
|
||||
void onNearbyChatContextMenuItemClicked(const LLSD& userdata);
|
||||
bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
|
||||
|
||||
LLLineEditor* getChatBox() { return mChatBox; }
|
||||
|
||||
//virtual void draw();
|
||||
|
||||
std::string getCurrentChat();
|
||||
|
||||
virtual BOOL handleKeyHere( KEY key, MASK mask );
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
|
||||
static void startChat(const char* line);
|
||||
static void stopChat();
|
||||
|
||||
static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate);
|
||||
static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);
|
||||
|
||||
void showHistory();
|
||||
void showTranslationCheckbox(BOOL show);
|
||||
|
||||
protected:
|
||||
static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str);
|
||||
static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata);
|
||||
static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata);
|
||||
void onChatBoxFocusReceived();
|
||||
|
||||
void sendChat( EChatType type );
|
||||
void onChatBoxCommit();
|
||||
void onChatFontChange(LLFontGL* fontp);
|
||||
|
||||
/* virtual */ bool applyRectControl();
|
||||
|
||||
void onToggleNearbyChatPanel();
|
||||
|
||||
static LLWString stripChannelNumber(const LLWString &mesg, S32* channel);
|
||||
EChatType processChatTypeTriggers(EChatType type, std::string &str);
|
||||
|
||||
void displaySpeakingIndicator();
|
||||
|
||||
void onCallButtonClicked();
|
||||
|
||||
// set the enable/disable state for the Call button
|
||||
virtual void enableDisableCallBtn();
|
||||
|
||||
// Which non-zero channel did we last chat on?
|
||||
static S32 sLastSpecialChatChannel;
|
||||
|
||||
LLLineEditor* mChatBox;
|
||||
LLOutputMonitorCtrl* mOutputMonitor;
|
||||
LLLocalSpeakerMgr* mSpeakerMgr;
|
||||
|
||||
S32 mExpandedHeight;
|
||||
|
||||
/*virtual*/ BOOL tick();
|
||||
|
||||
private:
|
||||
|
||||
void getAllowedRect (LLRect& rect);
|
||||
|
|
@ -68,14 +131,10 @@ private:
|
|||
void appendMessage(const LLChat& chat, const LLSD &args = 0);
|
||||
void onNearbySpeakers ();
|
||||
|
||||
|
||||
private:
|
||||
LLHandle<LLView> mPopupMenuHandle;
|
||||
std::vector<LLChat> mMessageArchive;
|
||||
LLChatHistory* mChatHistory;
|
||||
|
||||
std::vector<LLChat> mMessageArchive;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,709 +0,0 @@
|
|||
/**
|
||||
* @file llnearbychatbar.cpp
|
||||
* @brief LLNearbyChatBar class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&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 "message.h"
|
||||
|
||||
#include "llappviewer.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lltrans.h"
|
||||
#include "llimfloatercontainer.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llagent.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "llmultigesture.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "llanimationstates.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llnavigationbar.h"
|
||||
#include "llwindow.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llrootview.h"
|
||||
#include "llviewerchat.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "lltranslate.h"
|
||||
|
||||
#include "llresizehandle.h"
|
||||
|
||||
S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
|
||||
|
||||
const S32 EXPANDED_HEIGHT = 266;
|
||||
const S32 COLLAPSED_HEIGHT = 60;
|
||||
const S32 EXPANDED_MIN_HEIGHT = 150;
|
||||
|
||||
// legacy callback glue
|
||||
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
|
||||
|
||||
struct LLChatTypeTrigger {
|
||||
std::string name;
|
||||
EChatType type;
|
||||
};
|
||||
|
||||
static LLChatTypeTrigger sChatTypeTriggers[] = {
|
||||
{ "/whisper" , CHAT_TYPE_WHISPER},
|
||||
{ "/shout" , CHAT_TYPE_SHOUT}
|
||||
};
|
||||
|
||||
LLNearbyChatBar::LLNearbyChatBar(const LLSD& key)
|
||||
: LLIMConversation(key),
|
||||
mChatBox(NULL),
|
||||
mNearbyChat(NULL),
|
||||
mOutputMonitor(NULL),
|
||||
mSpeakerMgr(NULL),
|
||||
mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)
|
||||
{
|
||||
mSpeakerMgr = LLLocalSpeakerMgr::getInstance();
|
||||
}
|
||||
|
||||
//virtual
|
||||
BOOL LLNearbyChatBar::postBuild()
|
||||
{
|
||||
mChatBox = getChild<LLLineEditor>("chat_box");
|
||||
|
||||
mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this));
|
||||
mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this);
|
||||
mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this));
|
||||
mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChatBar::onChatBoxFocusReceived, this));
|
||||
|
||||
mChatBox->setIgnoreArrowKeys( FALSE );
|
||||
mChatBox->setCommitOnFocusLost( FALSE );
|
||||
mChatBox->setRevertOnEsc( FALSE );
|
||||
mChatBox->setIgnoreTab(TRUE);
|
||||
mChatBox->setPassDelete(TRUE);
|
||||
mChatBox->setReplaceNewlinesWithSpaces(FALSE);
|
||||
mChatBox->setEnableLineHistory(TRUE);
|
||||
mChatBox->setFont(LLViewerChat::getChatFont());
|
||||
|
||||
mNearbyChat = getChildView("nearby_chat");
|
||||
|
||||
LLUICtrl* show_btn = getChild<LLUICtrl>("show_nearby_chat");
|
||||
show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this));
|
||||
|
||||
mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
|
||||
mOutputMonitor->setVisible(FALSE);
|
||||
|
||||
gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE);
|
||||
|
||||
mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility"));
|
||||
|
||||
// Register for font change notifications
|
||||
LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1));
|
||||
|
||||
enableResizeCtrls(true, true, false);
|
||||
|
||||
addToHost();
|
||||
|
||||
return LLIMConversation::postBuild();;
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::enableDisableCallBtn()
|
||||
{
|
||||
// bool btn_enabled = LLAgent::isActionAllowed("speak");
|
||||
|
||||
getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/);
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::addToHost()
|
||||
{
|
||||
if (LLIMConversation::isChatMultiTab())
|
||||
{
|
||||
LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance();
|
||||
|
||||
if (im_box)
|
||||
{
|
||||
im_box->addFloater(this, FALSE, LLTabContainer::END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLNearbyChatBar::onOpen(const LLSD& key)
|
||||
{
|
||||
LLIMConversation::onOpen(key);
|
||||
showTranslationCheckbox(LLTranslate::isTranslationConfigured());
|
||||
}
|
||||
|
||||
bool LLNearbyChatBar::applyRectControl()
|
||||
{
|
||||
bool rect_controlled = LLFloater::applyRectControl();
|
||||
|
||||
if (!mNearbyChat->getVisible())
|
||||
{
|
||||
reshape(getRect().getWidth(), getMinHeight());
|
||||
enableResizeCtrls(true, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
enableResizeCtrls(true);
|
||||
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
|
||||
}
|
||||
|
||||
return rect_controlled;
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp)
|
||||
{
|
||||
// Update things with the new font whohoo
|
||||
if (mChatBox)
|
||||
{
|
||||
mChatBox->setFont(fontp);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLNearbyChatBar* LLNearbyChatBar::getInstance()
|
||||
{
|
||||
return LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar");
|
||||
}
|
||||
|
||||
//static
|
||||
//LLNearbyChatBar* LLNearbyChatBar::findInstance()
|
||||
//{
|
||||
// return LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar");
|
||||
//}
|
||||
|
||||
void LLNearbyChatBar::showHistory()
|
||||
{
|
||||
openFloater();
|
||||
|
||||
if (!getChildView("nearby_chat")->getVisible())
|
||||
{
|
||||
onToggleNearbyChatPanel();
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::showTranslationCheckbox(BOOL show)
|
||||
{
|
||||
getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show);
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::draw()
|
||||
{
|
||||
displaySpeakingIndicator();
|
||||
updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState());
|
||||
LLIMConversation::draw();
|
||||
}
|
||||
|
||||
std::string LLNearbyChatBar::getCurrentChat()
|
||||
{
|
||||
return mChatBox ? mChatBox->getText() : LLStringUtil::null;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask )
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
|
||||
if( KEY_RETURN == key && mask == MASK_CONTROL)
|
||||
{
|
||||
// shout
|
||||
sendChat(CHAT_TYPE_SHOUT);
|
||||
handled = TRUE;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str)
|
||||
{
|
||||
U32 in_len = in_str.length();
|
||||
S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers);
|
||||
|
||||
bool string_was_found = false;
|
||||
|
||||
for (S32 n = 0; n < cnt && !string_was_found; n++)
|
||||
{
|
||||
if (in_len <= sChatTypeTriggers[n].name.length())
|
||||
{
|
||||
std::string trigger_trunc = sChatTypeTriggers[n].name;
|
||||
LLStringUtil::truncate(trigger_trunc, in_len);
|
||||
|
||||
if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc))
|
||||
{
|
||||
*out_str = sChatTypeTriggers[n].name;
|
||||
string_was_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string_was_found;
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata)
|
||||
{
|
||||
LLFirstUse::otherAvatarChatFirst(false);
|
||||
|
||||
LLNearbyChatBar* self = (LLNearbyChatBar *)userdata;
|
||||
|
||||
LLWString raw_text = self->mChatBox->getWText();
|
||||
|
||||
// Can't trim the end, because that will cause autocompletion
|
||||
// to eat trailing spaces that might be part of a gesture.
|
||||
LLWStringUtil::trimHead(raw_text);
|
||||
|
||||
S32 length = raw_text.length();
|
||||
|
||||
if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences
|
||||
{
|
||||
gAgent.startTyping();
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
|
||||
/* Doesn't work -- can't tell the difference between a backspace
|
||||
that killed the selection vs. backspace at the end of line.
|
||||
if (length > 1
|
||||
&& text[0] == '/'
|
||||
&& key == KEY_BACKSPACE)
|
||||
{
|
||||
// the selection will already be deleted, but we need to trim
|
||||
// off the character before
|
||||
std::string new_text = raw_text.substr(0, length-1);
|
||||
self->mInputEditor->setText( new_text );
|
||||
self->mInputEditor->setCursorToEnd();
|
||||
length = length - 1;
|
||||
}
|
||||
*/
|
||||
|
||||
KEY key = gKeyboard->currentKey();
|
||||
|
||||
// Ignore "special" keys, like backspace, arrows, etc.
|
||||
if (length > 1
|
||||
&& raw_text[0] == '/'
|
||||
&& key < KEY_SPECIAL)
|
||||
{
|
||||
// we're starting a gesture, attempt to autocomplete
|
||||
|
||||
std::string utf8_trigger = wstring_to_utf8str(raw_text);
|
||||
std::string utf8_out_str(utf8_trigger);
|
||||
|
||||
if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
|
||||
S32 outlength = self->mChatBox->getLength(); // in characters
|
||||
|
||||
// Select to end of line, starting from the character
|
||||
// after the last one the user typed.
|
||||
self->mChatBox->setSelection(length, outlength);
|
||||
}
|
||||
else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part
|
||||
self->mChatBox->setCursorToEnd();
|
||||
}
|
||||
|
||||
//llinfos << "GESTUREDEBUG " << trigger
|
||||
// << " len " << length
|
||||
// << " outlen " << out_str.getLength()
|
||||
// << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata)
|
||||
{
|
||||
// stop typing animation
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::onChatBoxFocusReceived()
|
||||
{
|
||||
mChatBox->setEnabled(!gDisconnected);
|
||||
}
|
||||
|
||||
EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str)
|
||||
{
|
||||
U32 length = str.length();
|
||||
S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers);
|
||||
|
||||
for (S32 n = 0; n < cnt; n++)
|
||||
{
|
||||
if (length >= sChatTypeTriggers[n].name.length())
|
||||
{
|
||||
std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length());
|
||||
|
||||
if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name))
|
||||
{
|
||||
U32 trigger_length = sChatTypeTriggers[n].name.length();
|
||||
|
||||
// It's to remove space after trigger name
|
||||
if (length > trigger_length && str[trigger_length] == ' ')
|
||||
trigger_length++;
|
||||
|
||||
str = str.substr(trigger_length, length);
|
||||
|
||||
if (CHAT_TYPE_NORMAL == type)
|
||||
return sChatTypeTriggers[n].type;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::sendChat( EChatType type )
|
||||
{
|
||||
if (mChatBox)
|
||||
{
|
||||
LLWString text = mChatBox->getConvertedText();
|
||||
if (!text.empty())
|
||||
{
|
||||
// store sent line in history, duplicates will get filtered
|
||||
mChatBox->updateHistory();
|
||||
// Check if this is destined for another channel
|
||||
S32 channel = 0;
|
||||
stripChannelNumber(text, &channel);
|
||||
|
||||
std::string utf8text = wstring_to_utf8str(text);
|
||||
// Try to trigger a gesture, if not chat to a script.
|
||||
std::string utf8_revised_text;
|
||||
if (0 == channel)
|
||||
{
|
||||
// discard returned "found" boolean
|
||||
LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_revised_text = utf8text;
|
||||
}
|
||||
|
||||
utf8_revised_text = utf8str_trim(utf8_revised_text);
|
||||
|
||||
type = processChatTypeTriggers(type, utf8_revised_text);
|
||||
|
||||
if (!utf8_revised_text.empty())
|
||||
{
|
||||
// Chat with animation
|
||||
sendChatFromViewer(utf8_revised_text, type, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
mChatBox->setText(LLStringExplicit(""));
|
||||
}
|
||||
|
||||
gAgent.stopTyping();
|
||||
|
||||
// If the user wants to stop chatting on hitting return, lose focus
|
||||
// and go out of chat mode.
|
||||
if (gSavedSettings.getBOOL("CloseChatOnReturn"))
|
||||
{
|
||||
stopChat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLNearbyChatBar::onToggleNearbyChatPanel()
|
||||
{
|
||||
LLView* nearby_chat = getChildView("nearby_chat");
|
||||
|
||||
if (nearby_chat->getVisible())
|
||||
{
|
||||
if (!isMinimized())
|
||||
{
|
||||
mExpandedHeight = getRect().getHeight();
|
||||
}
|
||||
setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT);
|
||||
nearby_chat->setVisible(FALSE);
|
||||
reshape(getRect().getWidth(), COLLAPSED_HEIGHT);
|
||||
enableResizeCtrls(true, true, false);
|
||||
storeRectControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
nearby_chat->setVisible(TRUE);
|
||||
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
|
||||
reshape(getRect().getWidth(), mExpandedHeight);
|
||||
enableResizeCtrls(true);
|
||||
storeRectControl();
|
||||
}
|
||||
|
||||
gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible());
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::reloadMessages()
|
||||
{
|
||||
LLNearbyChat::getInstance()->reloadMessages();
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::setMinimized(BOOL b)
|
||||
{
|
||||
LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat");
|
||||
// when unminimizing with nearby chat visible, go ahead and kill off screen chats
|
||||
if (!b && nearby_chat->getVisible())
|
||||
{
|
||||
nearby_chat->removeScreenChat();
|
||||
}
|
||||
LLFloater::setMinimized(b);
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::onChatBoxCommit()
|
||||
{
|
||||
if (mChatBox->getText().length() > 0)
|
||||
{
|
||||
sendChat(CHAT_TYPE_NORMAL);
|
||||
}
|
||||
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::displaySpeakingIndicator()
|
||||
{
|
||||
LLSpeakerMgr::speaker_list_t speaker_list;
|
||||
LLUUID id;
|
||||
|
||||
id.setNull();
|
||||
mSpeakerMgr->update(TRUE);
|
||||
mSpeakerMgr->getSpeakerList(&speaker_list, FALSE);
|
||||
|
||||
for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
|
||||
{
|
||||
LLPointer<LLSpeaker> s = *i;
|
||||
if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
|
||||
{
|
||||
id = s->mID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!id.isNull())
|
||||
{
|
||||
mOutputMonitor->setVisible(TRUE);
|
||||
mOutputMonitor->setSpeakerId(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutputMonitor->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate)
|
||||
{
|
||||
sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate);
|
||||
}
|
||||
|
||||
void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
|
||||
{
|
||||
// Look for "/20 foo" channel chats.
|
||||
S32 channel = 0;
|
||||
LLWString out_text = stripChannelNumber(wtext, &channel);
|
||||
std::string utf8_out_text = wstring_to_utf8str(out_text);
|
||||
std::string utf8_text = wstring_to_utf8str(wtext);
|
||||
|
||||
utf8_text = utf8str_trim(utf8_text);
|
||||
if (!utf8_text.empty())
|
||||
{
|
||||
utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
|
||||
}
|
||||
|
||||
// Don't animate for chats people can't hear (chat to scripts)
|
||||
if (animate && (channel == 0))
|
||||
{
|
||||
if (type == CHAT_TYPE_WHISPER)
|
||||
{
|
||||
lldebugs << "You whisper " << utf8_text << llendl;
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START);
|
||||
}
|
||||
else if (type == CHAT_TYPE_NORMAL)
|
||||
{
|
||||
lldebugs << "You say " << utf8_text << llendl;
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START);
|
||||
}
|
||||
else if (type == CHAT_TYPE_SHOUT)
|
||||
{
|
||||
lldebugs << "You shout " << utf8_text << llendl;
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START);
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "send_chat_from_viewer() - invalid volume" << llendl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP)
|
||||
{
|
||||
lldebugs << "Channel chat: " << utf8_text << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
send_chat_from_viewer(utf8_out_text, type, channel);
|
||||
}
|
||||
|
||||
// static
|
||||
void LLNearbyChatBar::startChat(const char* line)
|
||||
{
|
||||
LLNearbyChatBar* cb = LLNearbyChatBar::getInstance();
|
||||
|
||||
if (cb )
|
||||
{
|
||||
cb->setVisible(TRUE);
|
||||
cb->setFocus(TRUE);
|
||||
cb->mChatBox->setFocus(TRUE);
|
||||
|
||||
if (line)
|
||||
{
|
||||
std::string line_string(line);
|
||||
cb->mChatBox->setText(line_string);
|
||||
}
|
||||
|
||||
cb->mChatBox->setCursorToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// Exit "chat mode" and do the appropriate focus changes
|
||||
// static
|
||||
void LLNearbyChatBar::stopChat()
|
||||
{
|
||||
LLNearbyChatBar* cb = LLNearbyChatBar::getInstance();
|
||||
|
||||
if (cb)
|
||||
{
|
||||
cb->mChatBox->setFocus(FALSE);
|
||||
|
||||
// stop typing animation
|
||||
gAgent.stopTyping();
|
||||
}
|
||||
}
|
||||
|
||||
// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20.
|
||||
// Otherwise returns input and channel 0.
|
||||
LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel)
|
||||
{
|
||||
if (mesg[0] == '/'
|
||||
&& mesg[1] == '/')
|
||||
{
|
||||
// This is a "repeat channel send"
|
||||
*channel = sLastSpecialChatChannel;
|
||||
return mesg.substr(2, mesg.length() - 2);
|
||||
}
|
||||
else if (mesg[0] == '/'
|
||||
&& mesg[1]
|
||||
&& LLStringOps::isDigit(mesg[1]))
|
||||
{
|
||||
// This a special "/20" speak on a channel
|
||||
S32 pos = 0;
|
||||
|
||||
// Copy the channel number into a string
|
||||
LLWString channel_string;
|
||||
llwchar c;
|
||||
do
|
||||
{
|
||||
c = mesg[pos+1];
|
||||
channel_string.push_back(c);
|
||||
pos++;
|
||||
}
|
||||
while(c && pos < 64 && LLStringOps::isDigit(c));
|
||||
|
||||
// Move the pointer forward to the first non-whitespace char
|
||||
// Check isspace before looping, so we can handle "/33foo"
|
||||
// as well as "/33 foo"
|
||||
while(c && iswspace(c))
|
||||
{
|
||||
c = mesg[pos+1];
|
||||
pos++;
|
||||
}
|
||||
|
||||
sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10);
|
||||
*channel = sLastSpecialChatChannel;
|
||||
return mesg.substr(pos, mesg.length() - pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is normal chat.
|
||||
*channel = 0;
|
||||
return mesg;
|
||||
}
|
||||
}
|
||||
|
||||
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_ChatFromViewer);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_ChatData);
|
||||
msg->addStringFast(_PREHASH_Message, utf8_out_text);
|
||||
msg->addU8Fast(_PREHASH_Type, type);
|
||||
msg->addS32("Channel", channel);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
|
||||
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
|
||||
}
|
||||
|
||||
class LLChatCommandHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
// not allowed from outside the app
|
||||
LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
|
||||
|
||||
// Your code here
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
bool retval = false;
|
||||
// Need at least 2 tokens to have a valid message.
|
||||
if (tokens.size() < 2)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 channel = tokens[0].asInteger();
|
||||
// VWR-19499 Restrict function to chat channels greater than 0.
|
||||
if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG))
|
||||
{
|
||||
retval = true;
|
||||
// Send unescaped message, see EXT-6353.
|
||||
std::string unescaped_mesg (LLURI::unescape(tokens[1].asString()));
|
||||
send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = false;
|
||||
// Tell us this is an unsupported SLurl.
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
// Creating the object registers with the dispatcher.
|
||||
LLChatCommandHandler gChatHandler;
|
||||
|
||||
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* @file llnearbychatbar.h
|
||||
* @brief LLNearbyChatBar class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&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 LL_LLNEARBYCHATBAR_H
|
||||
#define LL_LLNEARBYCHATBAR_H
|
||||
|
||||
#include "llimconversation.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "llchat.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llvoiceclient.h"
|
||||
#include "lloutputmonitorctrl.h"
|
||||
#include "llspeakers.h"
|
||||
|
||||
class LLNearbyChatBar : public LLIMConversation
|
||||
{
|
||||
public:
|
||||
// constructor for inline chat-bars (e.g. hosted in chat history window)
|
||||
LLNearbyChatBar(const LLSD& key);
|
||||
~LLNearbyChatBar() {}
|
||||
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
|
||||
static LLNearbyChatBar* getInstance();
|
||||
// static LLNearbyChatBar* findInstance();
|
||||
|
||||
void addToHost();
|
||||
|
||||
void reloadMessages();
|
||||
LLLineEditor* getChatBox() { return mChatBox; }
|
||||
|
||||
virtual void draw();
|
||||
|
||||
std::string getCurrentChat();
|
||||
virtual BOOL handleKeyHere( KEY key, MASK mask );
|
||||
|
||||
static void startChat(const char* line);
|
||||
static void stopChat();
|
||||
|
||||
static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate);
|
||||
static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);
|
||||
|
||||
void showHistory();
|
||||
void showTranslationCheckbox(BOOL show);
|
||||
/*virtual*/void setMinimized(BOOL b);
|
||||
|
||||
protected:
|
||||
static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str);
|
||||
static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata);
|
||||
static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata);
|
||||
void onChatBoxFocusReceived();
|
||||
|
||||
void sendChat( EChatType type );
|
||||
void onChatBoxCommit();
|
||||
void onChatFontChange(LLFontGL* fontp);
|
||||
|
||||
/* virtual */ bool applyRectControl();
|
||||
|
||||
void onToggleNearbyChatPanel();
|
||||
|
||||
static LLWString stripChannelNumber(const LLWString &mesg, S32* channel);
|
||||
EChatType processChatTypeTriggers(EChatType type, std::string &str);
|
||||
|
||||
void displaySpeakingIndicator();
|
||||
|
||||
// set the enable/disable state for the Call button
|
||||
virtual void enableDisableCallBtn();
|
||||
|
||||
// Which non-zero channel did we last chat on?
|
||||
static S32 sLastSpecialChatChannel;
|
||||
|
||||
LLLineEditor* mChatBox;
|
||||
LLView* mNearbyChat;
|
||||
LLOutputMonitorCtrl* mOutputMonitor;
|
||||
LLLocalSpeakerMgr* mSpeakerMgr;
|
||||
|
||||
S32 mExpandedHeight;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -29,14 +29,14 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llnearbychatbarlistener.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llchat.h"
|
||||
|
||||
|
||||
|
||||
LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar)
|
||||
LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar)
|
||||
: LLEventAPI("LLChatBar",
|
||||
"LLChatBar listener to (e.g.) sendChat, etc."),
|
||||
mChatbar(chatbar)
|
||||
|
|
|
|||
|
|
@ -33,17 +33,17 @@
|
|||
#include "lleventapi.h"
|
||||
|
||||
class LLSD;
|
||||
class LLNearbyChatBar;
|
||||
class LLNearbyChat;
|
||||
|
||||
class LLNearbyChatBarListener : public LLEventAPI
|
||||
{
|
||||
public:
|
||||
LLNearbyChatBarListener(LLNearbyChatBar & chatbar);
|
||||
LLNearbyChatBarListener(LLNearbyChat & chatbar);
|
||||
|
||||
private:
|
||||
void sendChat(LLSD const & chat_data) const;
|
||||
|
||||
LLNearbyChatBar & mChatbar;
|
||||
LLNearbyChat & mChatbar;
|
||||
};
|
||||
|
||||
#endif // LL_LLNEARBYCHATBARLISTENER_H
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
#include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance
|
||||
#include "llviewerwindow.h"//for screen channel position
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llrootview.h"
|
||||
#include "lllayoutstack.h"
|
||||
|
||||
|
|
@ -487,9 +487,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,
|
|||
if(chat_msg.mText.empty())
|
||||
return;//don't process empty messages
|
||||
|
||||
LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar");
|
||||
|
||||
LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat");
|
||||
LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
|
||||
|
||||
// Build notification data
|
||||
LLSD chat;
|
||||
|
|
@ -558,8 +556,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,
|
|||
sChatWatcher->post(chat);
|
||||
|
||||
|
||||
if( !chat_bar->isMinimized()
|
||||
&& nearby_chat->isInVisibleChain()
|
||||
if( nearby_chat->isInVisibleChain()
|
||||
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
|
||||
&& gSavedSettings.getBOOL("UseChatBubbles") )
|
||||
|| mChannel.isDead()
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "llfloaterreg.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llnotificationhandler.h"
|
||||
#include "llnotifications.h"
|
||||
#include "lltoastnotifypanel.h"
|
||||
|
|
@ -86,8 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)
|
|||
|
||||
// don't show toast if Nearby Chat is opened
|
||||
LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
|
||||
LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance();
|
||||
if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible())
|
||||
if (!nearby_chat->isMinimized() && nearby_chat->getVisible())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,85 +41,4 @@
|
|||
#include "llspeakers.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
LLPanelChatControlPanel::~LLPanelChatControlPanel()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLPanelChatControlPanel::postBuild()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
|
||||
{
|
||||
//Method is called twice for AdHoc and Group chat. Second time when server init reply received
|
||||
mSessionId = session_id;
|
||||
}
|
||||
|
||||
|
||||
LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
|
||||
mParticipantList(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLPanelGroupControlPanel::postBuild()
|
||||
{
|
||||
|
||||
return LLPanelChatControlPanel::postBuild();
|
||||
}
|
||||
|
||||
LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
|
||||
{
|
||||
delete mParticipantList;
|
||||
mParticipantList = NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLPanelGroupControlPanel::draw()
|
||||
{
|
||||
// Need to resort the participant list if it's in sort by recent speaker order.
|
||||
if (mParticipantList)
|
||||
mParticipantList->update();
|
||||
LLPanelChatControlPanel::draw();
|
||||
}
|
||||
|
||||
|
||||
void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata)
|
||||
{
|
||||
// TODO: Check this code when when sort order menu will be added. (EM)
|
||||
if (false && !mParticipantList)
|
||||
return;
|
||||
|
||||
std::string chosen_item = userdata.asString();
|
||||
|
||||
if (chosen_item == "sort_name")
|
||||
{
|
||||
mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
|
||||
{
|
||||
LLPanelChatControlPanel::setSessionId(session_id);
|
||||
|
||||
mGroupID = session_id;
|
||||
|
||||
// for group and Ad-hoc chat we need to include agent into list
|
||||
if(!mParticipantList)
|
||||
{
|
||||
LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id);
|
||||
mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLPanelAdHocControlPanel::postBuild()
|
||||
{
|
||||
//We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat
|
||||
return LLPanelChatControlPanel::postBuild();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,6 @@
|
|||
#include "llscriptfloater.h"
|
||||
#include "llfloatermodelpreview.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "llnearbychatbar.h"
|
||||
|
||||
// *NOTE: Please add files in alphabetical order to keep merges easy.
|
||||
|
||||
|
|
@ -187,8 +186,6 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);
|
||||
|
||||
LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
|
||||
LLFloaterReg::add("chat_bar", "floater_chat_bar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChatBar>);
|
||||
|
||||
LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
|
||||
|
||||
LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
|
||||
|
|
@ -211,6 +208,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
|
||||
LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
|
||||
|
||||
LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);
|
||||
LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);
|
||||
LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>);
|
||||
LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include "llviewermessage.h" // send_guid_sound_trigger
|
||||
#include "llviewernetwork.h"
|
||||
#include "llagent.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
|
||||
// Globals
|
||||
LLViewerGestureList gGestureList;
|
||||
|
|
@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat )
|
|||
{
|
||||
// Don't play nodding animation, since that might not blend
|
||||
// with the gesture animation.
|
||||
LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);
|
||||
LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include "llmath.h"
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "llmorphview.h"
|
||||
|
|
@ -534,7 +534,7 @@ void stop_moving( EKeystate s )
|
|||
void start_chat( EKeystate s )
|
||||
{
|
||||
// start chat
|
||||
LLNearbyChatBar::startChat(NULL);
|
||||
LLNearbyChat::startChat(NULL);
|
||||
}
|
||||
|
||||
void start_gesture( EKeystate s )
|
||||
|
|
@ -543,15 +543,15 @@ void start_gesture( EKeystate s )
|
|||
if (KEYSTATE_UP == s &&
|
||||
! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
|
||||
{
|
||||
if (LLNearbyChatBar::getInstance()->getCurrentChat().empty())
|
||||
if (LLNearbyChat::getInstance()->getCurrentChat().empty())
|
||||
{
|
||||
// No existing chat in chat editor, insert '/'
|
||||
LLNearbyChatBar::startChat("/");
|
||||
LLNearbyChat::startChat("/");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't overwrite existing text in chat editor
|
||||
LLNearbyChatBar::startChat(NULL);
|
||||
LLNearbyChat::startChat(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@
|
|||
#include "llviewerjoystick.h"
|
||||
#include "llviewernetwork.h"
|
||||
#include "llpostprocess.h"
|
||||
#include "llnearbychatbar.h"
|
||||
#include "llnearbychat.h"
|
||||
#include "llagentui.h"
|
||||
#include "llwearablelist.h"
|
||||
|
||||
|
|
@ -2482,7 +2482,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
|
|||
// Traverses up the hierarchy
|
||||
if( keyboard_focus )
|
||||
{
|
||||
LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar");
|
||||
LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar");
|
||||
|
||||
if (nearby_chat)
|
||||
{
|
||||
|
|
@ -2549,11 +2549,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
|
|||
if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&
|
||||
!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
|
||||
{
|
||||
LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox();
|
||||
LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar")->getChatBox();
|
||||
if (chat_editor)
|
||||
{
|
||||
// passing NULL here, character will be added later when it is handled by character handler.
|
||||
LLNearbyChatBar::getInstance()->startChat(NULL);
|
||||
LLNearbyChat::getInstance()->startChat(NULL);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,202 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater
|
||||
open_positioning="specified"
|
||||
specified_left="10"
|
||||
specified_bottom="10"
|
||||
background_visible="true"
|
||||
default_tab_group="1"
|
||||
height="355"
|
||||
help_topic="chat_bar"
|
||||
layout="topleft"
|
||||
name="chat_bar"
|
||||
can_dock="false"
|
||||
can_minimize="true"
|
||||
can_close="true"
|
||||
visible="false"
|
||||
width="394"
|
||||
can_resize="true"
|
||||
can_tear_off="false"
|
||||
min_width="250"
|
||||
min_height="80"
|
||||
single_instance="true"
|
||||
title="Nearby chat">
|
||||
<floater.string name="call_btn_start">VoicePTT_Off</floater.string>
|
||||
<floater.string name="call_btn_stop">VoicePTT_On</floater.string>
|
||||
<floater.string
|
||||
name="collapse_icon"
|
||||
value="TabIcon_Open_Off"/>
|
||||
<floater.string
|
||||
name="expand_icon"
|
||||
value="TabIcon_Close_Off"/>
|
||||
<floater.string
|
||||
name="tear_off_icon"
|
||||
value="tearoffbox.tga"/>
|
||||
<floater.string
|
||||
name="return_icon"
|
||||
value="Icon_Dock_Foreground"/>
|
||||
<view
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="contents_view"
|
||||
top="0"
|
||||
left="0"
|
||||
height="355"
|
||||
width="394">
|
||||
<panel
|
||||
follows="left|top|right"
|
||||
layout="topleft"
|
||||
name="toolbar_panel"
|
||||
top="0"
|
||||
left="0"
|
||||
height="35"
|
||||
width="394">
|
||||
<menu_button
|
||||
menu_filename="menu_im_session_showmodes.xml"
|
||||
follows="top|left"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Left_Over"
|
||||
image_overlay="OptionsMenu_Off"
|
||||
image_selected="Toolbar_Left_Selected"
|
||||
image_unselected="Toolbar_Left_Off"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="view_options_btn"
|
||||
top="5"
|
||||
width="31" />
|
||||
<button
|
||||
follows="top|left"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="AddItem_Off"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left_pad="4"
|
||||
name="add_btn"
|
||||
width="31">
|
||||
<commit_callback
|
||||
function="Chats.add" />
|
||||
</button>
|
||||
<button
|
||||
follows="top|left"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Right_Over"
|
||||
image_overlay="VoicePTT_Off"
|
||||
image_selected="Toolbar_Right_Selected"
|
||||
image_unselected="Toolbar_Right_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left_pad="4"
|
||||
name="voice_call_btn"
|
||||
width="31">
|
||||
<commit_callback
|
||||
function="Chats.add" />
|
||||
</button>
|
||||
<button
|
||||
follows="right|top"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="Icon_Close_Foreground"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left="283"
|
||||
name="close_btn"
|
||||
width="31">
|
||||
</button>
|
||||
<button
|
||||
follows="right|top"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="TabIcon_Open_Off"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left_pad="5"
|
||||
name="expand_collapse_btn"
|
||||
width="31">
|
||||
</button>
|
||||
<button
|
||||
follows="right|top"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="tearoffbox.tga"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left_pad="5"
|
||||
name="tear_off_btn"
|
||||
width="31">
|
||||
</button>
|
||||
</panel>
|
||||
<panel
|
||||
top="35"
|
||||
left="0"
|
||||
class="panel_nearby_chat"
|
||||
follow="all"
|
||||
width="390"
|
||||
height="0"
|
||||
visible="false"
|
||||
filename="panel_nearby_chat.xml"
|
||||
name="nearby_chat" />
|
||||
<panel
|
||||
width="390"
|
||||
height="10"
|
||||
visible="true" />
|
||||
<panel width="394"
|
||||
height="31"
|
||||
left="0"
|
||||
name="bottom_panel"
|
||||
bottom="-1"
|
||||
follows="left|right|bottom"
|
||||
tab_group="1">
|
||||
<line_editor
|
||||
border_style="line"
|
||||
border_thickness="1"
|
||||
follows="left|right"
|
||||
height="20"
|
||||
label="Click here to chat."
|
||||
layout="topleft"
|
||||
left="1"
|
||||
max_length_bytes="1023"
|
||||
name="chat_box"
|
||||
tool_tip="Press Enter to say, Ctrl+Enter to shout"
|
||||
top="2"
|
||||
width="384" />
|
||||
<output_monitor
|
||||
auto_update="true"
|
||||
follows="right"
|
||||
draw_border="false"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left_pad="-24"
|
||||
mouse_opaque="true"
|
||||
name="chat_zone_indicator"
|
||||
top="6"
|
||||
visible="true"
|
||||
width="20" />
|
||||
<button
|
||||
follows="right"
|
||||
visible="false"
|
||||
is_toggle="true"
|
||||
width="20"
|
||||
top="2"
|
||||
layout="topleft"
|
||||
left_pad="12"
|
||||
image_disabled="ComboButton_UpOff"
|
||||
image_unselected="ComboButton_UpOff"
|
||||
image_selected="ComboButton_On"
|
||||
image_pressed="ComboButton_UpSelected"
|
||||
image_pressed_selected="ComboButton_Selected"
|
||||
height="23"
|
||||
chrome="true"
|
||||
name="show_nearby_chat"
|
||||
tool_tip="Shows/hides nearby chat log">
|
||||
</button>
|
||||
</panel>
|
||||
</view>
|
||||
</floater>
|
||||
|
|
@ -138,18 +138,24 @@
|
|||
top_pad="0"
|
||||
left="0">
|
||||
<layout_panel
|
||||
name="im_control_panel_holder"
|
||||
name="speakers_list_panel"
|
||||
min_width="115"
|
||||
width="150"
|
||||
height="310"
|
||||
auto_resize="false">
|
||||
<panel
|
||||
name="panel_im_control_panel"
|
||||
layout="topleft"
|
||||
height="310"
|
||||
width="150"
|
||||
follows="all"/>
|
||||
</layout_panel>
|
||||
<avatar_list
|
||||
color="DkGray2"
|
||||
follows="all"
|
||||
height="100"
|
||||
ignore_online_status="true"
|
||||
layout="topleft"
|
||||
name="speakers_list"
|
||||
opaque="false"
|
||||
show_info_btn="true"
|
||||
show_profile_btn="false"
|
||||
show_speaking_indicator="false"
|
||||
width="145" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
default_tab_group="3"
|
||||
left="0"
|
||||
|
|
@ -158,27 +164,82 @@
|
|||
height="200"
|
||||
width="254"
|
||||
user_resize="true">
|
||||
<chat_history
|
||||
font="SansSerifSmall"
|
||||
follows="all"
|
||||
height="170"
|
||||
name="chat_history"
|
||||
parse_highlights="true"
|
||||
parse_urls="true"
|
||||
left="1"
|
||||
width="249">
|
||||
</chat_history>
|
||||
<line_editor
|
||||
bottom="0"
|
||||
follows="left|right|bottom"
|
||||
font="SansSerifSmall"
|
||||
height="20"
|
||||
label="To"
|
||||
layout="bottomleft"
|
||||
name="chat_editor"
|
||||
tab_group="3"
|
||||
width="249">
|
||||
</line_editor>
|
||||
<layout_stack
|
||||
animate="true"
|
||||
default_tab_group="2"
|
||||
follows="all"
|
||||
height="200"
|
||||
width="254"
|
||||
layout="topleft"
|
||||
orientation="vertical"
|
||||
name="chat_area"
|
||||
tab_group="1"
|
||||
left_pad="0"
|
||||
top="0">
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="26"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="translate_chat_checkbox_lp"
|
||||
top_delta="0"
|
||||
visible="true"
|
||||
width="230">
|
||||
<check_box
|
||||
top="10"
|
||||
control_name="TranslateChat"
|
||||
enabled="true"
|
||||
height="16"
|
||||
label="Translate chat"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="translate_chat_checkbox"
|
||||
width="230" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="170"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="translate_chat_checkbox_lp"
|
||||
top_delta="0"
|
||||
visible="true"
|
||||
width="230">
|
||||
<chat_history
|
||||
font="SansSerifSmall"
|
||||
follows="all"
|
||||
height="170"
|
||||
name="chat_history"
|
||||
parse_highlights="true"
|
||||
parse_urls="true"
|
||||
left="1"
|
||||
width="229">
|
||||
</chat_history>
|
||||
<line_editor
|
||||
bottom="0"
|
||||
follows="left|right|bottom"
|
||||
font="SansSerifSmall"
|
||||
height="20"
|
||||
label="To"
|
||||
layout="bottomleft"
|
||||
name="chat_editor"
|
||||
tab_group="3"
|
||||
width="230">
|
||||
</line_editor>
|
||||
<output_monitor
|
||||
auto_update="true"
|
||||
follows="right"
|
||||
draw_border="false"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left_pad="-24"
|
||||
mouse_opaque="true"
|
||||
name="chat_zone_indicator"
|
||||
top="6"
|
||||
visible="true"
|
||||
width="20" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</view>
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<panel
|
||||
border="false"
|
||||
follows="all"
|
||||
height="215"
|
||||
name="panel_im_control_panel"
|
||||
width="150">
|
||||
<layout_stack
|
||||
mouse_opaque="false"
|
||||
border_size="0"
|
||||
clip="false"
|
||||
follows="all"
|
||||
height="215"
|
||||
layout="topleft"
|
||||
left="3"
|
||||
name="vertical_stack"
|
||||
orientation="vertical"
|
||||
top="0"
|
||||
width="147">
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
follows="top|left"
|
||||
height="130"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
min_height="0"
|
||||
mouse_opaque="false"
|
||||
width="147"
|
||||
top="0"
|
||||
name="speakers_list_panel">
|
||||
<avatar_list
|
||||
color="DkGray2"
|
||||
follows="all"
|
||||
height="130"
|
||||
ignore_online_status="true"
|
||||
layout="topleft"
|
||||
name="speakers_list"
|
||||
opaque="false"
|
||||
show_info_btn="true"
|
||||
show_profile_btn="false"
|
||||
show_speaking_indicator="false"
|
||||
width="147" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
follows="top|left|right"
|
||||
height="25"
|
||||
layout="topleft"
|
||||
min_height="25"
|
||||
width="130"
|
||||
name="call_btn_panel"
|
||||
visible="false">
|
||||
<button
|
||||
follows="all"
|
||||
height="20"
|
||||
label="Call"
|
||||
name="call_btn"
|
||||
width="130"
|
||||
top="0" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
follows="top|left|right"
|
||||
height="25"
|
||||
layout="topleft"
|
||||
min_height="25"
|
||||
width="130"
|
||||
name="end_call_btn_panel"
|
||||
visible="false">
|
||||
<button
|
||||
follows="all"
|
||||
height="20"
|
||||
label="Leave Call"
|
||||
name="end_call_btn"
|
||||
top="0"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
follows="top|left|right"
|
||||
height="25"
|
||||
layout="topleft"
|
||||
min_height="25"
|
||||
width="130"
|
||||
name="voice_ctrls_btn_panel"
|
||||
visible="false">
|
||||
<button
|
||||
follows="all"
|
||||
height="20"
|
||||
label="Voice Controls"
|
||||
name="voice_ctrls_btn"
|
||||
top="0"
|
||||
use_ellipses="true" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<panel
|
||||
border="false"
|
||||
follows="all"
|
||||
height="238"
|
||||
name="panel_im_control_panel"
|
||||
width="150">
|
||||
<layout_stack
|
||||
mouse_opaque="false"
|
||||
border_size="0"
|
||||
clip="false"
|
||||
follows="all"
|
||||
height="238"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="vertical_stack"
|
||||
orientation="vertical"
|
||||
top="0"
|
||||
width="145">
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
follows="top|left"
|
||||
height="100"
|
||||
layout="topleft"
|
||||
min_height="0"
|
||||
mouse_opaque="false"
|
||||
width="145"
|
||||
top="0"
|
||||
name="speakers_list_panel">
|
||||
<avatar_list
|
||||
color="DkGray2"
|
||||
follows="all"
|
||||
height="100"
|
||||
ignore_online_status="true"
|
||||
layout="topleft"
|
||||
name="speakers_list"
|
||||
opaque="false"
|
||||
show_info_btn="true"
|
||||
show_profile_btn="false"
|
||||
show_speaking_indicator="false"
|
||||
width="145" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
follows="top|left|right"
|
||||
height="28"
|
||||
layout="topleft"
|
||||
min_height="28"
|
||||
width="130"
|
||||
name="voice_ctrls_btn_panel"
|
||||
visible="false">
|
||||
<button
|
||||
follows="all"
|
||||
height="23"
|
||||
label="Open Voice Controls"
|
||||
name="voice_ctrls_btn"
|
||||
use_ellipses="true" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
|
|
@ -6,16 +6,17 @@
|
|||
help_topic="nearby_chat"
|
||||
layout="topleft"
|
||||
name="nearby_chat"
|
||||
width="394">
|
||||
width="242"
|
||||
height="169">
|
||||
<layout_stack
|
||||
follows="all"
|
||||
height="278"
|
||||
height="164"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="stack"
|
||||
top="5"
|
||||
orientation="vertical"
|
||||
width="394">
|
||||
width="242">
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
height="26"
|
||||
|
|
@ -24,7 +25,7 @@
|
|||
name="translate_chat_checkbox_lp"
|
||||
top_delta="0"
|
||||
visible="true"
|
||||
width="387">
|
||||
width="230">
|
||||
<check_box
|
||||
top="10"
|
||||
control_name="TranslateChat"
|
||||
|
|
@ -34,15 +35,15 @@
|
|||
layout="topleft"
|
||||
left="5"
|
||||
name="translate_chat_checkbox"
|
||||
width="374" />
|
||||
width="230" />
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
height="256"
|
||||
height="138"
|
||||
left_delta="0"
|
||||
layout="topleft"
|
||||
name="chat_history_lp"
|
||||
width="394">
|
||||
width="242">
|
||||
<chat_history
|
||||
bg_readonly_color="ChatHistoryBgColor"
|
||||
bg_writeable_color="ChatHistoryBgColor"
|
||||
|
|
@ -50,7 +51,7 @@
|
|||
layout="topleft"
|
||||
left="5"
|
||||
left_widget_pad="0"
|
||||
height="240"
|
||||
height="138"
|
||||
name="chat_history"
|
||||
parse_highlights="true"
|
||||
parse_urls="true"
|
||||
|
|
@ -58,7 +59,7 @@
|
|||
text_color="ChatHistoryTextColor"
|
||||
text_readonly_color="ChatHistoryTextColor"
|
||||
top="0"
|
||||
width="384" />
|
||||
width="237" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue