summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llfolderview.cpp2
-rwxr-xr-xindra/llui/llfolderviewitem.cpp32
-rwxr-xr-xindra/llui/llfolderviewitem.h2
-rw-r--r--indra/llui/llfolderviewmodel.h7
-rw-r--r--indra/llui/lllayoutstack.cpp44
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llappviewer.cpp1
-rw-r--r--indra/newview/llcallfloater.cpp822
-rw-r--r--indra/newview/llcallfloater.h275
-rwxr-xr-xindra/newview/llconversationview.cpp31
-rwxr-xr-xindra/newview/llconversationview.h1
-rw-r--r--indra/newview/llimconversation.cpp217
-rw-r--r--indra/newview/llimconversation.h30
-rw-r--r--indra/newview/llimfloater.cpp89
-rw-r--r--indra/newview/llimfloater.h13
-rw-r--r--indra/newview/llimfloatercontainer.cpp177
-rw-r--r--indra/newview/llimfloatercontainer.h4
-rw-r--r--indra/newview/llparticipantlist.cpp343
-rw-r--r--indra/newview/llparticipantlist.h66
-rw-r--r--indra/newview/llviewerfloaterreg.cpp1
-rw-r--r--indra/newview/llvoicevivox.cpp3
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_voice_controls.xml155
-rw-r--r--indra/newview/skins/default/xui/en/panel_conversation_list_item.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml2
26 files changed, 402 insertions, 1950 deletions
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index c31a832141..a33ffc4240 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -566,7 +566,7 @@ void LLFolderView::sanitizeSelection()
parent_folder;
parent_folder = parent_folder->getParentFolder())
{
- if (parent_folder->getViewModelItem()->potentiallyVisible())
+ if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible())
{
// give initial selection to first ancestor folder that potentially passes the filter
if (!new_selection)
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 21fb9bff90..822534ffcf 100755
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -169,7 +169,6 @@ BOOL LLFolderViewItem::postBuild()
// Destroys the object
LLFolderViewItem::~LLFolderViewItem( void )
{
- delete mViewModelItem;
mViewModelItem = NULL;
}
@@ -473,8 +472,9 @@ void LLFolderViewItem::rename(const std::string& new_name)
const std::string& LLFolderViewItem::getName( void ) const
{
- return getViewModelItem()->getName();
- }
+ static const std::string noName("");
+ return getViewModelItem() ? getViewModelItem()->getName() : noName;
+}
// LLView functionality
BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask )
@@ -1563,7 +1563,7 @@ BOOL LLFolderViewFolder::isRemovable()
void LLFolderViewFolder::addItem(LLFolderViewItem* item)
{
if (item->getParentFolder())
-{
+ {
item->getParentFolder()->extractItem(item);
}
item->setParentFolder(this);
@@ -1574,7 +1574,13 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item)
item->setVisible(FALSE);
addChild(item);
- getViewModelItem()->addChild(item->getViewModelItem());
+
+ // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it
+ // Note: this happens when models are created before views or shared between views
+ if (!item->getViewModelItem()->hasParent())
+ {
+ getViewModelItem()->addChild(item->getViewModelItem());
+ }
//TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria
//// Traverse parent folders and update creation date and resort, if necessary
@@ -1593,11 +1599,11 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item)
// this is an internal method used for adding items to folders.
void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
- {
+{
if (folder->mParentFolder)
- {
+ {
folder->mParentFolder->extractItem(folder);
- }
+ }
folder->mParentFolder = this;
mFolders.push_back(folder);
folder->setOrigin(0, 0);
@@ -1607,9 +1613,15 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
//folder->requestArrange();
//requestSort();
- addChild( folder );
- getViewModelItem()->addChild(folder->getViewModelItem());
+ addChild(folder);
+
+ // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it
+ // Note: this happens when models are created before views or shared between views
+ if (!folder->getViewModelItem()->hasParent())
+ {
+ getViewModelItem()->addChild(folder->getViewModelItem());
}
+}
void LLFolderViewFolder::requestArrange()
{
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 8bb73bcf5d..b157aabdcf 100755
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -87,7 +87,7 @@ protected:
bool mLabelWidthDirty;
S32 mLabelPaddingRight;
LLFolderViewFolder* mParentFolder;
- LLFolderViewModelItem* mViewModelItem;
+ LLPointer<LLFolderViewModelItem> mViewModelItem;
LLFontGL::StyleFlags mLabelStyle;
std::string mLabelSuffix;
LLUIImagePtr mIcon,
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index c6030c9b71..7019857c0f 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -129,10 +129,11 @@ public:
// This is am abstract base class that users of the folderview classes
// would use to bridge the folder view with the underlying data
-class LLFolderViewModelItem
+class LLFolderViewModelItem : public LLRefCount
{
public:
- virtual ~LLFolderViewModelItem( void ) {};
+ LLFolderViewModelItem() { }
+ virtual ~LLFolderViewModelItem() { }
virtual void update() {} //called when drawing
virtual const std::string& getName() const = 0;
@@ -201,6 +202,7 @@ public:
virtual S32 getSortVersion() = 0;
virtual void setSortVersion(S32 version) = 0;
virtual void setParent(LLFolderViewModelItem* parent) = 0;
+ virtual bool hasParent() = 0;
protected:
@@ -331,6 +333,7 @@ public:
protected:
virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; }
+ virtual bool hasParent() { return mParent != NULL; }
S32 mSortVersion;
bool mPassedFilter;
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 1f2496a8e7..0674275612 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -36,7 +36,7 @@
#include "llcriticaldamp.h"
#include "boost/foreach.hpp"
-static const F32 MIN_FRACTIONAL_SIZE = 0.0f;
+static const F32 MIN_FRACTIONAL_SIZE = 0.00001f;
static const F32 MAX_FRACTIONAL_SIZE = 1.f;
static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
@@ -71,7 +71,7 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
mCollapseAmt(0.f),
mVisibleAmt(1.f), // default to fully visible
mResizeBar(NULL),
- mFractionalSize(MIN_FRACTIONAL_SIZE),
+ mFractionalSize(0.f),
mTargetDim(0),
mIgnoreReshape(false),
mOrientation(LLLayoutStack::HORIZONTAL)
@@ -521,7 +521,7 @@ void LLLayoutStack::updateFractionalSizes()
{
if (panelp->mAutoResize)
{
- total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim());
+ total_resizable_dim += llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
}
}
@@ -672,12 +672,12 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
S32 new_dim = (mOrientation == HORIZONTAL)
? new_rect.getWidth()
: new_rect.getHeight();
- S32 delta_dim = new_dim - resized_panel->getVisibleDim();
- if (delta_dim == 0) return;
+ S32 delta_panel_dim = new_dim - resized_panel->getVisibleDim();
+ if (delta_panel_dim == 0) return;
F32 total_visible_fraction = 0.f;
F32 delta_auto_resize_headroom = 0.f;
- F32 original_auto_resize_headroom = 0.f;
+ F32 old_auto_resize_headroom = 0.f;
LLLayoutPanel* other_resize_panel = NULL;
LLLayoutPanel* following_panel = NULL;
@@ -686,7 +686,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
{
if (panelp->mAutoResize)
{
- original_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
+ old_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
if (panelp->getVisible() && !panelp->mCollapsed)
{
total_visible_fraction += panelp->mFractionalSize;
@@ -704,25 +704,24 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
}
-
if (resized_panel->mAutoResize)
{
if (!other_resize_panel || !other_resize_panel->mAutoResize)
{
- delta_auto_resize_headroom += delta_dim;
+ delta_auto_resize_headroom += delta_panel_dim;
}
}
else
{
if (!other_resize_panel || other_resize_panel->mAutoResize)
{
- delta_auto_resize_headroom -= delta_dim;
+ delta_auto_resize_headroom -= delta_panel_dim;
}
}
F32 fraction_given_up = 0.f;
F32 fraction_remaining = 1.f;
- F32 updated_auto_resize_headroom = original_auto_resize_headroom + delta_auto_resize_headroom;
+ F32 new_auto_resize_headroom = old_auto_resize_headroom + delta_auto_resize_headroom;
enum
{
@@ -734,7 +733,14 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
- if (!panelp->getVisible() || panelp->mCollapsed) continue;
+ if (!panelp->getVisible() || panelp->mCollapsed)
+ {
+ if (panelp->mAutoResize)
+ {
+ fraction_remaining -= panelp->mFractionalSize;
+ }
+ continue;
+ }
if (panelp == resized_panel)
{
@@ -746,9 +752,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
case BEFORE_RESIZED_PANEL:
if (panelp->mAutoResize)
{ // freeze current size as fraction of overall auto_resize space
- F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f
+ F32 fractional_adjustment_factor = new_auto_resize_headroom == 0.f
? 1.f
- : original_auto_resize_headroom / updated_auto_resize_headroom;
+ : old_auto_resize_headroom / new_auto_resize_headroom;
F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
MIN_FRACTIONAL_SIZE,
MAX_FRACTIONAL_SIZE);
@@ -765,9 +771,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
case RESIZED_PANEL:
if (panelp->mAutoResize)
{ // freeze new size as fraction
- F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)
+ F32 new_fractional_size = (new_auto_resize_headroom == 0.f)
? MAX_FRACTIONAL_SIZE
- : llclamp(total_visible_fraction * (F32)(new_dim - (panelp->getRelevantMinDim() - 1)) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
+ : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
fraction_remaining -= panelp->mFractionalSize;
panelp->mFractionalSize = new_fractional_size;
@@ -791,7 +797,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
else
{
F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)
- / updated_auto_resize_headroom,
+ / new_auto_resize_headroom,
MIN_FRACTIONAL_SIZE,
MAX_FRACTIONAL_SIZE);
fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
@@ -800,7 +806,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
else
{
- panelp->mTargetDim -= delta_dim;
+ panelp->mTargetDim -= delta_panel_dim;
}
which_panel = AFTER_RESIZED_PANEL;
break;
@@ -816,7 +822,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
}
updateLayout();
- normalizeFractionalSizes();
+ //normalizeFractionalSizes();
}
void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c6ba8a22bd..2c7e96f1e4 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -117,7 +117,6 @@ set(viewer_SOURCE_FILES
llbrowsernotification.cpp
llbuycurrencyhtml.cpp
llcallbacklist.cpp
- llcallfloater.cpp
llcallingcard.cpp
llcapabilitylistener.cpp
llcaphttpsender.cpp
@@ -701,7 +700,6 @@ set(viewer_HEADER_FILES
llbreadcrumbview.h
llbuycurrencyhtml.h
llcallbacklist.h
- llcallfloater.h
llcallingcard.h
llcapabilitylistener.h
llcapabilityprovider.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0537487ca3..5694cb9f30 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -12395,17 +12395,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>SpeakerParticipantDefaultOrder</key>
- <map>
- <key>Comment</key>
- <string>Order for displaying speakers in voice controls. 0 = alphabetical. 1 = recent.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>SpeakerParticipantRemoveDelay</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d6c781020d..b23e5866dc 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -95,7 +95,6 @@
#include "llweb.h"
#include "llsecondlifeurls.h"
#include "llupdaterservice.h"
-#include "llcallfloater.h"
#include "llfloatertexturefetchdebugger.h"
#include "llspellcheck.h"
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
deleted file mode 100644
index e767609d74..0000000000
--- a/indra/newview/llcallfloater.cpp
+++ /dev/null
@@ -1,822 +0,0 @@
-/**
- * @file llcallfloater.cpp
- * @author Mike Antipov
- * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...).
- *
- * $LicenseInfo:firstyear=2009&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 "llcallfloater.h"
-
-#include "llnotificationsutil.h"
-#include "lltrans.h"
-
-#include "llagent.h"
-#include "llagentdata.h" // for gAgentID
-#include "llavatarnamecache.h"
-#include "llavatariconctrl.h"
-#include "llavatarlist.h"
-#include "lldraghandle.h"
-#include "llimfloater.h"
-#include "llimview.h"
-#include "llfloaterreg.h"
-#include "llparticipantlist.h"
-#include "llspeakers.h"
-#include "lltextutil.h"
-#include "lltransientfloatermgr.h"
-#include "llviewercontrol.h"
-#include "llviewerdisplayname.h"
-#include "llviewerwindow.h"
-#include "llvoicechannel.h"
-#include "llviewerparcelmgr.h"
-#include "llfirstuse.h"
-
-static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids);
-void reshape_floater(LLCallFloater* floater, S32 delta_height);
-
-class LLNonAvatarCaller : public LLAvatarListItem
-{
-public:
- LLNonAvatarCaller() : LLAvatarListItem(false)
- {
-
- }
- BOOL postBuild()
- {
- BOOL rv = LLAvatarListItem::postBuild();
-
- if (rv)
- {
- setOnline(true);
- showLastInteractionTime(false);
- setShowProfileBtn(false);
- setShowInfoBtn(false);
- mAvatarIcon->setValue("Avaline_Icon");
- mAvatarIcon->setToolTip(std::string(""));
- }
- return rv;
- }
-
- void setName(const std::string& name)
- {
- const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
- LLAvatarListItem::setAvatarName(formatted_phone);
- LLAvatarListItem::setAvatarToolTip(formatted_phone);
- }
-
- void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
-};
-
-
-static void* create_non_avatar_caller(void*)
-{
- return new LLNonAvatarCaller;
-}
-
-LLVoiceChannel* LLCallFloater::sCurrentVoiceChannel = NULL;
-
-LLCallFloater::LLCallFloater(const LLSD& key)
-: LLTransientDockableFloater(NULL, false, key)
-, mSpeakerManager(NULL)
-, mParticipants(NULL)
-, mAvatarList(NULL)
-, mNonAvatarCaller(NULL)
-, mVoiceType(VC_LOCAL_CHAT)
-, mAgentPanel(NULL)
-, mSpeakingIndicator(NULL)
-, mIsModeratorMutedVoice(false)
-, mInitParticipantsVoiceState(false)
-{
- static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10);
- mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
-
- mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
- LLVoiceClient::instance().addObserver(this);
- LLTransientFloaterMgr::getInstance()->addControlView(this);
-
- // update the agent's name if display name setting change
- LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLCallFloater::updateAgentModeratorState, this));
- LLViewerDisplayName::addNameChangedCallback(boost::bind(&LLCallFloater::updateAgentModeratorState, this));
-
-}
-
-LLCallFloater::~LLCallFloater()
-{
- resetVoiceRemoveTimers();
- delete mSpeakerDelayRemover;
-
- delete mParticipants;
- mParticipants = NULL;
-
- mAvatarListRefreshConnection.disconnect();
- mVoiceChannelStateChangeConnection.disconnect();
-
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->removeObserver(this);
- }
- LLTransientFloaterMgr::getInstance()->removeControlView(this);
-}
-
-// virtual
-BOOL LLCallFloater::postBuild()
-{
- mAvatarList = getChild<LLAvatarList>("speakers_list");
- mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this));
-
- childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
-
- mNonAvatarCaller = findChild<LLNonAvatarCaller>("non_avatar_caller");
- mNonAvatarCaller->setVisible(FALSE);
-
- initAgentData();
-
- connectToChannel(LLVoiceChannel::getCurrentVoiceChannel());
-
- updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
-
- updateSession();
- return TRUE;
-}
-
-// virtual
-void LLCallFloater::onOpen(const LLSD& /*key*/)
-{
- LLFirstUse::speak(false);
-}
-
-// virtual
-void LLCallFloater::draw()
-{
- // we have to refresh participants to display ones not in voice as disabled.
- // It should be done only when she joins or leaves voice chat.
- // But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement.
- // *TODO: mantipov: remove from draw()
-
- // NOTE: it looks like calling onChange() here is not necessary,
- // but sometime it is not called properly from the observable object.
- // Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent)
-// onChange();
-
- bool is_moderator_muted = LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID);
-
- if (mIsModeratorMutedVoice != is_moderator_muted)
- {
- setModeratorMutedVoice(is_moderator_muted);
- }
-
- // Need to resort the participant list if it's in sort by recent speaker order.
- if (mParticipants)
- mParticipants->update();
-
- LLFloater::draw();
-}
-
-// virtual
-void LLCallFloater::setFocus( BOOL b )
-{
- LLFloater::setFocus(b);
-
- // Force using active floater transparency (STORM-730).
- // We have to override setFocus() for LLCallFloater because selecting an item
- // of the voice morphing combobox causes the floater to lose focus and thus become transparent.
- updateTransparency(TT_ACTIVE);
-}
-
-// virtual
-void LLCallFloater::onParticipantsChanged()
-{
- if (NULL == mParticipants) return;
- updateParticipantsVoiceState();
-
- // Add newly joined participants.
- uuid_vec_t speakers_uuids;
- get_voice_participants_uuids(speakers_uuids);
- for (uuid_vec_t::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++)
- {
- mParticipants->addAvatarIDExceptAgent(*it);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-/// PRIVATE SECTION
-//////////////////////////////////////////////////////////////////////////
-
-void LLCallFloater::leaveCall()
-{
- LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
- if (voice_channel)
- {
- gIMMgr->endCall(voice_channel->getSessionID());
- }
-}
-
-void LLCallFloater::updateSession()
-{
- LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
- if (voice_channel)
- {
- LL_DEBUGS("Voice") << "Current voice channel: " << voice_channel->getSessionID() << LL_ENDL;
-
- if (mSpeakerManager && voice_channel->getSessionID() == mSpeakerManager->getSessionID())
- {
- LL_DEBUGS("Voice") << "Speaker manager is already set for session: " << voice_channel->getSessionID() << LL_ENDL;
- return;
- }
- else
- {
- mSpeakerManager = NULL;
- }
- }
-
- const LLUUID& session_id = voice_channel ? voice_channel->getSessionID() : LLUUID::null;
-
- LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
- if (im_session)
- {
- mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
- switch (im_session->mType)
- {
- case IM_NOTHING_SPECIAL:
- case IM_SESSION_P2P_INVITE:
- mVoiceType = VC_PEER_TO_PEER;
-
- if (!im_session->mOtherParticipantIsAvatar)
- {
- mVoiceType = VC_PEER_TO_PEER_AVALINE;
- }
- break;
- case IM_SESSION_CONFERENCE_START:
- case IM_SESSION_GROUP_START:
- case IM_SESSION_INVITE:
- if (gAgent.isInGroup(session_id))
- {
- mVoiceType = VC_GROUP_CHAT;
- }
- else
- {
- mVoiceType = VC_AD_HOC_CHAT;
- }
- break;
- default:
- llwarning("Failed to determine voice call IM type", 0);
- mVoiceType = VC_GROUP_CHAT;
- break;
- }
- }
-
- if (NULL == mSpeakerManager)
- {
- // By default show nearby chat participants
- mSpeakerManager = LLLocalSpeakerMgr::getInstance();
- LL_DEBUGS("Voice") << "Set DEFAULT speaker manager" << LL_ENDL;
- mVoiceType = VC_LOCAL_CHAT;
- }
-
- updateTitle();
-
- // Hide "Leave Call" button for nearby chat
- bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
- getChildView("leave_call_btn_panel")->setVisible( !is_local_chat);
-
- refreshParticipantList();
- updateAgentModeratorState();
-
- // Show floater for voice calls & only in CONNECTED to voice channel state
- if (!is_local_chat &&
- voice_channel &&
- LLVoiceChannel::STATE_CONNECTED == voice_channel->getState())
- {
- LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
- bool show_me = !(im_floater && im_floater->getVisible());
- if (show_me)
- {
- setVisible(true);
- }
- }
-}
-
-void LLCallFloater::refreshParticipantList()
-{
- bool non_avatar_caller = VC_PEER_TO_PEER_AVALINE == mVoiceType;
-
- if (non_avatar_caller)
- {
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSpeakerManager->getSessionID());
- mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID);
- mNonAvatarCaller->setName(session->mName);
- }
-
- mNonAvatarCaller->setVisible(non_avatar_caller);
- mAvatarList->setVisible(!non_avatar_caller);
-
- if (!non_avatar_caller)
- {
- llassert(mParticipants == NULL); // check for possible memory leak
- mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, mConversationViewModel, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false);
- mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
- const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
- mParticipants->setSortOrder(LLParticipantList::EParticipantSortOrder(speaker_sort_order));
-
- if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
- {
- mAvatarList->setNoItemsCommentText(getString("no_one_near"));
- }
-
- // we have to made delayed initialization of voice state of participant list.
- // it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed().
- mInitParticipantsVoiceState = true;
- }
-}
-
-void LLCallFloater::onAvatarListRefreshed()
-{
- if (mInitParticipantsVoiceState)
- {
- initParticipantsVoiceState();
- mInitParticipantsVoiceState = false;
- }
- else
- {
- updateParticipantsVoiceState();
- }
-}
-
-// static
-// This entry point now disable, but left for later use.
-void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/)
-{
- LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel();
-
- // *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO
- // it sill be sent for the same channel again (when state is changed).
- // So, lets ignore this call.
- if (channel == sCurrentVoiceChannel) return;
-
- LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls");
-
- call_floater->connectToChannel(channel);
-}
-
-void LLCallFloater::onAvatarNameCache(const LLUUID& agent_id,
- const LLAvatarName& av_name)
-{
- LLStringUtil::format_map_t args;
- args["[NAME]"] = av_name.getCompleteName();
- std::string title = getString("title_peer_2_peer", args);
- setTitle(title);
-}
-
-void LLCallFloater::updateTitle()
-{
- LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
- if (mVoiceType == VC_PEER_TO_PEER)
- {
- LLUUID session_id = voice_channel->getSessionID();
- LLIMModel::LLIMSession* im_session =
- LLIMModel::getInstance()->findIMSession(session_id);
- if (im_session)
- {
- LLAvatarNameCache::get(im_session->mOtherParticipantID,
- boost::bind(&LLCallFloater::onAvatarNameCache,
- this, _1, _2));
- return;
- }
- }
- std::string title;
- switch (mVoiceType)
- {
- case VC_LOCAL_CHAT:
- title = getString("title_nearby");
- break;
- case VC_PEER_TO_PEER:
- case VC_PEER_TO_PEER_AVALINE:
- {
- title = voice_channel->getSessionName();
-
- if (VC_PEER_TO_PEER_AVALINE == mVoiceType)
- {
- title = LLTextUtil::formatPhoneNumber(title);
- }
-
- LLStringUtil::format_map_t args;
- args["[NAME]"] = title;
- title = getString("title_peer_2_peer", args);
- }
- break;
- case VC_AD_HOC_CHAT:
- title = getString("title_adhoc");
- break;
- case VC_GROUP_CHAT:
- {
- LLStringUtil::format_map_t args;
- args["[GROUP]"] = voice_channel->getSessionName();
- title = getString("title_group", args);
- }
- break;
- }
-
- setTitle(title);
-}
-
-void LLCallFloater::initAgentData()
-{
- mAgentPanel = getChild<LLPanel> ("my_panel");
-
- if ( mAgentPanel )
- {
- mAgentPanel->getChild<LLUICtrl>("user_icon")->setValue(gAgentID);
-
- // Just use display name, because it's you
- LLAvatarName av_name;
- LLAvatarNameCache::get( gAgentID, &av_name );
- mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(av_name.mDisplayName);
-
- mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator");
- mSpeakingIndicator->setSpeakerId(gAgentID);
- }
-}
-
-void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)
-{
- mIsModeratorMutedVoice = moderator_muted;
-
- if (moderator_muted)
- {
- LLNotificationsUtil::add("VoiceIsMutedByModerator");
- }
- mSpeakingIndicator->setIsMuted(moderator_muted);
-}
-
-void LLCallFloater::onModeratorNameCache(const LLAvatarName& av_name)
-{
- std::string name;
- name = av_name.mDisplayName;
-
- if(mSpeakerManager && gAgent.isInGroup(mSpeakerManager->getSessionID()))
- {
- // This method can be called when LLVoiceChannel.mState == STATE_NO_CHANNEL_INFO
- // in this case there are not any speakers yet.
- if (mSpeakerManager->findSpeaker(gAgentID))
- {
- // Agent is Moderator
- if (mSpeakerManager->findSpeaker(gAgentID)->mIsModerator)
-
- {
- const std::string moderator_indicator(LLTrans::getString("IM_moderator_label"));
- name += " " + moderator_indicator;
- }
- }
- }
- mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(name);
-}
-
-void LLCallFloater::updateAgentModeratorState()
-{
- LLAvatarNameCache::get(gAgentID, boost::bind(&LLCallFloater::onModeratorNameCache, this, _2));
-}
-
-static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids)
-{
- // Get a list of participants from VoiceClient
- std::set<LLUUID> participants;
- LLVoiceClient::getInstance()->getParticipantList(participants);
-
- for (std::set<LLUUID>::const_iterator iter = participants.begin();
- iter != participants.end(); ++iter)
- {
- speakers_uuids.push_back(*iter);
- }
-
-}
-
-void LLCallFloater::initParticipantsVoiceState()
-{
- // Set initial status for each participant in the list.
- std::vector<LLPanel*> items;
- mAvatarList->getItems(items);
- std::vector<LLPanel*>::const_iterator
- it = items.begin(),
- it_end = items.end();
-
-
- uuid_vec_t speakers_uuids;
- get_voice_participants_uuids(speakers_uuids);
-
- for(; it != it_end; ++it)
- {
- LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
-
- if (!item) continue;
-
- LLUUID speaker_id = item->getAvatarId();
-
- uuid_vec_t::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id);
-
- // If an avatarID assigned to a panel is found in a speakers list
- // obtained from VoiceClient we assign the JOINED status to the owner
- // of this avatarID.
- if (speaker_iter != speakers_uuids.end())
- {
- setState(item, STATE_JOINED);
- }
- else
- {
- LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id);
- // If someone has already left the call before, we create his
- // avatar row panel with HAS_LEFT status and remove it after
- // the timeout, otherwise we create a panel with INVITED status
- if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall)
- {
- setState(item, STATE_LEFT);
- }
- else
- {
- setState(item, STATE_INVITED);
- }
- }
- }
-}
-
-void LLCallFloater::updateParticipantsVoiceState()
-{
- uuid_vec_t speakers_list;
-
- // Get a list of participants from VoiceClient
- uuid_vec_t speakers_uuids;
- get_voice_participants_uuids(speakers_uuids);
-
- // Updating the status for each participant already in list.
- std::vector<LLPanel*> items;
- mAvatarList->getItems(items);
- std::vector<LLPanel*>::const_iterator
- it = items.begin(),
- it_end = items.end();
-
- for(; it != it_end; ++it)
- {
- LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
- if (!item) continue;
-
- const LLUUID participant_id = item->getAvatarId();
- bool found = false;
-
- uuid_vec_t::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), participant_id);
-
- LL_DEBUGS("Voice") << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << LL_ENDL;
-
- // If an avatarID assigned to a panel is found in a speakers list
- // obtained from VoiceClient we assign the JOINED status to the owner
- // of this avatarID.
- if (speakers_iter != speakers_uuids.end())
- {
- setState(item, STATE_JOINED);
-
- LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id);
- if (speaker.isNull())
- continue;
- speaker->mHasLeftCurrentCall = FALSE;
-
- speakers_uuids.erase(speakers_iter);
- found = true;
- }
-
- if (!found)
- {
- updateNotInVoiceParticipantState(item);
- }
- }
-}
-
-void LLCallFloater::updateNotInVoiceParticipantState(LLAvatarListItem* item)
-{
- LLUUID participant_id = item->getAvatarId();
- ESpeakerState current_state = getState(participant_id);
-
- switch (current_state)
- {
- case STATE_JOINED:
- // If an avatarID is not found in a speakers list from VoiceClient and
- // a panel with this ID has a JOINED status this means that this person
- // HAS LEFT the call.
- setState(item, STATE_LEFT);
-
- {
- LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id);
- if (speaker.notNull())
- {
- speaker->mHasLeftCurrentCall = TRUE;
- }
- }
- break;
- case STATE_LEFT:
- // nothing to do. These states should not be changed.
- break;
- case STATE_INVITED:
- // If avatar was invited into group chat and went offline it is still exists in mSpeakerStateMap
- // If it goes online it will be rendered as JOINED via LAvatarListItem.
- // Lets update its visual representation. See EXT-6660
- case STATE_UNKNOWN:
- // If an avatarID is not found in a speakers list from VoiceClient and
- // a panel with this ID has an UNKNOWN status this means that this person
- // HAS ENTERED session but it is not in voice chat yet. So, set INVITED status
- setState(item, STATE_INVITED);
- break;
- default:
- // for possible new future states.
- llwarns << "Unsupported (" << getState(participant_id) << ") state for: " << item->getAvatarName() << llendl;
- break;
- }
-}
-
-void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
-{
- // *HACK: mantipov: sometimes such situation is possible while switching to voice channel:
-/*
- - voice channel is switched to the one user is joining
- - participant list is initialized with voice states: agent is in voice
- - than such log messages were found (with agent UUID)
- - LLVivoxProtocolParser::process_impl: parsing: <Response requestId="22" action="Session.MediaDisconnect.1"><ReturnCode>0</ReturnCode><Results><StatusCode>0</StatusCode><StatusString /></Results><InputXml><Request requestId="22" action="Session.MediaDisconnect.1"><SessionGroupHandle>9</SessionGroupHandle><SessionHandle>12</SessionHandle><Media>Audio</Media></Request></InputXml></Response>
- - LLVoiceClient::sessionState::removeParticipant: participant "sip:x2pwNkMbpR_mK4rtB_awASA==@bhr.vivox.com" (da9c0d90-c6e9-47f9-8ae2-bb41fdac0048) removed.
- - and than while updating participants voice states agent is marked as HAS LEFT
- - next updating of LLVoiceClient state makes agent JOINED
- So, lets skip HAS LEFT state for agent's avatar
-*/
- if (STATE_LEFT == state && item->getAvatarId() == gAgentID) return;
-
- setState(item->getAvatarId(), state);
-
- switch (state)
- {
- case STATE_INVITED:
- item->setState(LLAvatarListItem::IS_VOICE_INVITED);
- break;
- case STATE_JOINED:
- removeVoiceRemoveTimer(item->getAvatarId());
- item->setState(LLAvatarListItem::IS_VOICE_JOINED);
- break;
- case STATE_LEFT:
- {
- setVoiceRemoveTimer(item->getAvatarId());
- item->setState(LLAvatarListItem::IS_VOICE_LEFT);
- }
- break;
- default:
- llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl;
- break;
- }
-}
-
-void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
-{
- mSpeakerDelayRemover->setActionTimer(voice_speaker_id);
-}
-
-bool LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
-{
- uuid_vec_t& speaker_uuids = mAvatarList->getIDs();
- uuid_vec_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id);
- if(pos != speaker_uuids.end())
- {
- speaker_uuids.erase(pos);
- mAvatarList->setDirty();
- }
-
- return false;
-}
-
-
-void LLCallFloater::resetVoiceRemoveTimers()
-{
- mSpeakerDelayRemover->removeAllTimers();
-}
-
-void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
-{
- mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
-}
-
-bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
-{
- bool is_valid = true;
- switch (mVoiceType)
- {
- case VC_LOCAL_CHAT:
- {
- // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice).
- uuid_vec_t speakers;
- get_voice_participants_uuids(speakers);
- is_valid = std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end();
- }
- break;
- case VC_GROUP_CHAT:
- // if participant had left this call before do not allow add her again. See EXT-4216.
- // but if she Join she will be added into the list from the LLCallFloater::onChange()
- is_valid = STATE_LEFT != getState(speaker_id);
- break;
- default:
- // do nothing. required for Linux build
- break;
- }
-
- return is_valid;
-}
-
-void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
-{
- mVoiceChannelStateChangeConnection.disconnect();
-
- sCurrentVoiceChannel = channel;
-
- mVoiceChannelStateChangeConnection = sCurrentVoiceChannel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2));
-
- updateState(channel->getState());
-}
-
-void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
-{
- // check is voice operational and if it doesn't work hide VCP (EXT-4397)
- if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking())
- {
- updateState(new_state);
- }
- else
- {
- closeFloater();
- }
-}
-
-void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
-{
- LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceChannel->getSessionName() << LL_ENDL;
- if (LLVoiceChannel::STATE_CONNECTED == new_state)
- {
- updateSession();
- }
- else
- {
- reset(new_state);
- }
-}
-
-void LLCallFloater::reset(const LLVoiceChannel::EState& new_state)
-{
- // lets forget states from the previous session
- // for timers...
- resetVoiceRemoveTimers();
-
- // ...and for speaker state
- mSpeakerStateMap.clear();
-
- delete mParticipants;
- mParticipants = NULL;
- mAvatarList->clear();
-
- // These ifs were added instead of simply showing "loading" to make VCP work correctly in parcels
- // with disabled voice (EXT-4648 and EXT-4649)
- if (!LLViewerParcelMgr::getInstance()->allowAgentVoice() && LLVoiceChannel::STATE_HUNG_UP == new_state)
- {
- // hides "Leave Call" when call is ended in parcel with disabled voice- hiding usually happens in
- // updateSession() which won't be called here because connect to nearby voice never happens
- getChildView("leave_call_btn_panel")->setVisible( false);
- // setting title to nearby chat an "no one near..." text- because in region with disabled
- // voice we won't have chance to really connect to nearby, so VCP is changed here manually
- setTitle(getString("title_nearby"));
- mAvatarList->setNoItemsCommentText(getString("no_one_near"));
- }
- // "loading" is shown only when state is "ringing" to avoid showing it in nearby chat vcp
- // of parcels with disabled voice all the time- "no_one_near" is now shown there (EXT-4648)
- else if (new_state == LLVoiceChannel::STATE_RINGING)
- {
- // update floater to show Loading while waiting for data.
- mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
- }
-
- mAvatarList->setVisible(TRUE);
- mNonAvatarCaller->setVisible(FALSE);
-
- mSpeakerManager = NULL;
-}
-
-//EOF
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
deleted file mode 100644
index e1c7b3f43a..0000000000
--- a/indra/newview/llcallfloater.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- * @file llcallfloater.h
- * @author Mike Antipov
- * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...).
- *
- * $LicenseInfo:firstyear=2009&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_LLCALLFLOATER_H
-#define LL_LLCALLFLOATER_H
-
-#include "lltransientdockablefloater.h"
-#include "llvoicechannel.h"
-#include "llvoiceclient.h"
-#include "llconversationmodel.h"
-
-class LLAvatarList;
-class LLAvatarListItem;
-class LLAvatarName;
-class LLNonAvatarCaller;
-class LLOutputMonitorCtrl;
-class LLParticipantList;
-class LLSpeakerMgr;
-class LLSpeakersDelayActionsStorage;
-
-/**
- * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron
- * on the Speak button. It can be torn-off and freely positioned onscreen.
- *
- * When the Resident is engaged in Voice Chat, the Voice Control Panel provides control
- * over the audible volume of each of the other participants, the Resident's own Voice
- * Morphing settings (if she has subscribed to enable the feature), and Voice Recording.
- *
- * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel
- * also provides a 'Leave Call' button to allow the Resident to leave that voice channel.
- */
-class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver
-{
-public:
-
- LOG_CLASS(LLCallFloater);
-
- LLCallFloater(const LLSD& key);
- ~LLCallFloater();
-
- /*virtual*/ BOOL postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
- /*virtual*/ void draw();
- /*virtual*/ void setFocus( BOOL b );
-
- /**
- * Is called by LLVoiceClient::notifyParticipantObservers when voice participant list is changed.
- *
- * Refreshes list to display participants not in voice as disabled.
- */
- /*virtual*/ void onParticipantsChanged();
-
- static void onCurrentChannelChanged(const LLUUID& session_id);
-
-private:
- typedef enum e_voice_controls_type
- {
- VC_LOCAL_CHAT,
- VC_GROUP_CHAT,
- VC_AD_HOC_CHAT,
- VC_PEER_TO_PEER,
- VC_PEER_TO_PEER_AVALINE
- }EVoiceControls;
-
- typedef enum e_speaker_state
- {
- STATE_UNKNOWN,
- STATE_INVITED,
- STATE_JOINED,
- STATE_LEFT,
- } ESpeakerState;
-
- typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t;
-
- void leaveCall();
-
- /**
- * Updates mSpeakerManager and list according to current Voice Channel
- *
- * It compares mSpeakerManager & current Voice Channel session IDs.
- * If they are different gets Speaker manager related to current channel and updates channel participant list.
- */
- void updateSession();
-
- /**
- * Refreshes participant list according to current Voice Channel
- */
- void refreshParticipantList();
-
- /**
- * Handles event on avatar list is refreshed after it was marked dirty.
- *
- * It sets initial participants voice states (once after the first refreshing)
- * and updates voice states each time anybody is joined/left voice chat in session.
- */
- void onAvatarListRefreshed();
-
- /**
- * Updates window title with an avatar name
- */
- void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
-
- void updateTitle();
- void initAgentData();
- void setModeratorMutedVoice(bool moderator_muted);
- void updateAgentModeratorState();
- void onModeratorNameCache(const LLAvatarName& av_name);
-
- /**
- * Sets initial participants voice states in avatar list (Invited, Joined, Has Left).
- *
- * @see refreshParticipantList()
- * @see onAvatarListRefreshed()
- * @see mInitParticipantsVoiceState
- */
- void initParticipantsVoiceState();
-
- /**
- * Updates participants voice states in avatar list (Invited, Joined, Has Left).
- *
- * @see onAvatarListRefreshed()
- * @see onChanged()
- */
- void updateParticipantsVoiceState();
-
- /**
- * Updates voice state of participant not in current voice channel depend on its current state.
- */
- void updateNotInVoiceParticipantState(LLAvatarListItem* item);
- void setState(LLAvatarListItem* item, ESpeakerState state);
- void setState(const LLUUID& speaker_id, ESpeakerState state)
- {
- lldebugs << "Storing state: " << speaker_id << ", " << state << llendl;
- mSpeakerStateMap[speaker_id] = state;
- }
-
- ESpeakerState getState(const LLUUID& speaker_id)
- {
- lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl;
-
- return mSpeakerStateMap[speaker_id];
- }
-
- /**
- * Instantiates new LLAvatarListItemRemoveTimer and adds it into the map if it is not already created.
- *
- * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list when timer expires.
- */
- void setVoiceRemoveTimer(const LLUUID& voice_speaker_id);
-
- /**
- * Removes specified by UUID Avatar List item.
- *
- * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list.
- */
- bool removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
-
- /**
- * Deletes all timers from the list to prevent started timers from ticking after destruction
- * and after switching on another voice channel.
- */
- void resetVoiceRemoveTimers();
-
- /**
- * Removes specified by UUID timer from the map.
- *
- * @param voice_speaker_id LLUUID of Avatar List item whose timer should be removed from the map.
- */
- void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id);
-
- /**
- * Called by LLParticipantList before adding a speaker to the participant list.
- *
- * If false is returned, the speaker will not be added to the list.
- *
- * @param speaker_id Speaker to validate.
- * @return true if this is a valid speaker, false otherwise.
- */
- bool validateSpeaker(const LLUUID& speaker_id);
-
- /**
- * Connects to passed channel to be updated according to channel's voice states.
- */
- void connectToChannel(LLVoiceChannel* channel);
-
- /**
- * Callback to process changing of voice channel's states.
- */
- void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
-
- /**
- * Updates floater according to passed channel's voice state.
- */
- void updateState(const LLVoiceChannel::EState& new_state);
-
- /**
- * Resets floater to be ready to show voice participants.
- *
- * Clears all data from the latest voice session.
- */
- void reset(const LLVoiceChannel::EState& new_state);
-
-private:
- speaker_state_map_t mSpeakerStateMap;
- LLSpeakerMgr* mSpeakerManager;
- LLParticipantList* mParticipants;
- LLAvatarList* mAvatarList;
- LLConversationViewModel mConversationViewModel;
- LLNonAvatarCaller* mNonAvatarCaller;
- EVoiceControls mVoiceType;
- LLPanel* mAgentPanel;
- LLOutputMonitorCtrl* mSpeakingIndicator;
- bool mIsModeratorMutedVoice;
-
- /**
- * Flag indicated that participants voice states should be initialized.
- *
- * It is used due to Avatar List has delayed refreshing after it content is changed.
- * Real initializing is performed when Avatar List is first time refreshed.
- *
- * @see onAvatarListRefreshed()
- * @see initParticipantsVoiceState()
- */
- bool mInitParticipantsVoiceState;
-
- boost::signals2::connection mAvatarListRefreshConnection;
-
-
- /**
- * time out speakers when they are not part of current session
- */
- LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
-
- /**
- * Stores reference to current voice channel.
- *
- * Is used to ignore voice channel changed callback for the same channel.
- *
- * @see onCurrentChannelChanged()
- */
- static LLVoiceChannel* sCurrentVoiceChannel;
-
- /* virtual */
- LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
-
- boost::signals2::connection mVoiceChannelStateChangeConnection;
-};
-
-
-#endif //LL_LLCALLFLOATER_H
-
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 34b5976e3e..ac5b2ad6ac 100755
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -108,7 +108,7 @@ BOOL LLConversationViewSession::postBuild()
mSessionTitle = mItemPanel->getChild<LLTextBox>("conversation_title");
mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewSession::onCurrentVoiceSessionChanged, this, _1));
- mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicatorn");
+ mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem());
if (vmi)
@@ -244,7 +244,6 @@ void LLConversationViewSession::toggleOpen()
}
}
-
void LLConversationViewSession::toggleMinimizedMode(bool is_minimized)
{
mMinimizedMode = is_minimized;
@@ -261,8 +260,9 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)
{
// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized
// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here
- LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem);
- LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID());
+ LLFolderViewModelItem* item = mViewModelItem;
+ LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
+ LLFloater* session_floater = LLIMConversation::getConversation(session_uuid);
if (session_floater && !session_floater->getHost() && !session_floater->isMinimized())
{
@@ -429,13 +429,30 @@ void LLConversationViewParticipant::draw()
LLView::draw();
}
+// virtual
+S32 LLConversationViewParticipant::arrange(S32* width, S32* height)
+{
+ //Need to call arrange first since it computes value used in getIndentation()
+ S32 arranged = LLFolderViewItem::arrange(width, height);
+
+ //Adjusts the avatar icon based upon the indentation
+ LLRect avatarRect(getIndentation(),
+ mAvatarIcon->getRect().mTop,
+ getIndentation() + mAvatarIcon->getRect().getWidth(),
+ mAvatarIcon->getRect().mBottom);
+ mAvatarIcon->setShape(avatarRect);
+
+ return arranged;
+}
+
void LLConversationViewParticipant::refresh()
{
// Refresh the participant view from its model data
- LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem());
+ LLConversationItemParticipant* vmi = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem());
vmi->resetRefresh();
- // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh()
+ // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
+ mSpeakingIndicator->setIsMuted(vmi->isMuted());
// Do the regular upstream refresh
LLFolderViewItem::refresh();
@@ -496,7 +513,7 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask )
S32 LLConversationViewParticipant::getLabelXPos()
{
- return mAvatarIcon->getRect().mRight + mIconPad;
+ return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad;
}
// static
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index ac91d2d26f..43547d155b 100755
--- a/indra/newview/llconversationview.h
+++ b/indra/newview/llconversationview.h
@@ -135,6 +135,7 @@ protected:
void initFromParams(const Params& params);
BOOL postBuild();
/*virtual*/ void draw();
+ /*virtual*/ S32 arrange(S32* width, S32* height);
void onInfoBtnClick();
diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp
index 51e4fbfe19..a321b3545a 100644
--- a/indra/newview/llimconversation.cpp
+++ b/indra/newview/llimconversation.cpp
@@ -29,6 +29,8 @@
#include "llimconversation.h"
+#include "llagent.h"
+#include "llavataractions.h"
#include "llchatentry.h"
#include "llchathistory.h"
#include "llchiclet.h"
@@ -49,7 +51,7 @@ LLIMConversation::LLIMConversation(const LLSD& session_id)
, mTearOffBtn(NULL)
, mCloseBtn(NULL)
, mSessionID(session_id.asUUID())
- , mParticipantList(NULL)
+ , mConversationsRoot(NULL)
, mChatHistory(NULL)
, mInputEditor(NULL)
, mInputEditorTopPad(0)
@@ -74,12 +76,6 @@ LLIMConversation::LLIMConversation(const LLSD& session_id)
LLIMConversation::~LLIMConversation()
{
- if (mParticipantList)
- {
- delete mParticipantList;
- mParticipantList = NULL;
- }
-
delete mRefreshTimer;
}
@@ -178,7 +174,8 @@ void LLIMConversation::addToHost(const LLUUID& session_id)
conversp->setHost(floater_container);
conversp->setHost(NULL);
}
-
+ // Added floaters share some state (like sort order) with their host
+ conversp->setSortOrder(floater_container->getSortOrder());
}
}
}
@@ -193,11 +190,39 @@ BOOL LLIMConversation::postBuild()
mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this));
- mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
-
mTearOffBtn = getChild<LLButton>("tear_off_btn");
mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this));
+ mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
+
+ // Create a root view folder for all participants
+ LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel);
+ LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
+ p.rect = LLRect(0, 0, getRect().getWidth(), 0);
+ p.parent_panel = mParticipantListPanel;
+ p.listener = base_item;
+ p.view_model = &mConversationViewModel;
+ p.root = NULL;
+ p.use_ellipses = true;
+ mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
+ mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ // Add a scroller for the folder (participant) view
+ LLRect scroller_view_rect = mParticipantListPanel->getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());
+ scroller_params.rect(scroller_view_rect);
+ LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
+ scroller->setFollowsAll();
+
+ // Insert that scroller into the panel widgets hierarchy and folder view
+ mParticipantListPanel->addChild(scroller);
+ scroller->addChild(mConversationsRoot);
+ mConversationsRoot->setScrollContainer(scroller);
+ mConversationsRoot->setFollowsAll();
+ mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox);
+
+
mChatHistory = getChild<LLChatHistory>("chat_history");
mInputEditor = getChild<LLChatEntry>("chat_editor");
@@ -210,9 +235,7 @@ BOOL LLIMConversation::postBuild()
setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);
- buildParticipantList();
-
- updateHeaderAndToolbar();
+ buildConversationViewParticipant();
mSaveRect = isTornOff();
initRectControl();
@@ -226,26 +249,32 @@ BOOL LLIMConversation::postBuild()
result = LLDockableFloater::postBuild();
}
+ refreshConversation();
+
return result;
}
-void LLIMConversation::draw()
+LLParticipantList* LLIMConversation::getParticipantList()
{
- LLTransientDockableFloater::draw();
+ return dynamic_cast<LLParticipantList*>(LLIMFloaterContainer::getInstance()->getSessionModel(mSessionID));
+}
+void LLIMConversation::draw()
+{
if (mRefreshTimer->hasExpired())
{
- if (mParticipantList)
+ if (getParticipantList())
{
- mParticipantList->update();
+ getParticipantList()->update();
}
- refresh();
- updateHeaderAndToolbar();
+ refreshConversation();
// Restart the refresh timer
mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);
}
+
+ LLTransientDockableFloater::draw();
}
void LLIMConversation::enableDisableCallBtn()
@@ -332,41 +361,144 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args)
}
-void LLIMConversation::buildParticipantList()
+void LLIMConversation::buildConversationViewParticipant()
{
- if (mIsNearbyChat)
+ // Clear the widget list since we are rebuilding afresh from the model
+ conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
+ while (widget_it != mConversationsWidgets.end())
{
- LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance();
- mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false);
+ removeConversationViewParticipant(widget_it->first);
+ // Iterators are invalidated by erase so we need to pick begin again
+ widget_it = mConversationsWidgets.begin();
+ }
+
+ // Get the model list
+ LLParticipantList* item = getParticipantList();
+ if (!item)
+ {
+ // Nothing to do if the model list is empty
+ return;
+ }
+
+ // Create the participants widgets now
+ LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin();
+ LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd();
+ while (current_participant_model != end_participant_model)
+ {
+ LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model);
+ addConversationViewParticipant(participant_model);
+ current_participant_model++;
+ }
+}
+
+void LLIMConversation::addConversationViewParticipant(LLConversationItem* participant_model)
+{
+ // Check if the model already has an associated view
+ LLUUID uuid = participant_model->getUUID();
+ LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
+
+ // If not already present, create the participant view and attach it to the root, otherwise, just refresh it
+ if (widget)
+ {
+ updateConversationViewParticipant(uuid); // overkill?
}
else
{
- LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
- // for group and ad-hoc chat we need to include agent into list
- if(!mIsP2PChat && mSessionID.notNull() && speaker_manager)
- {
- delete mParticipantList; // remove the old list and create a new one if the session id has changed
- mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false);
- }
+ LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model);
+ mConversationsWidgets[uuid] = participant_view;
+ participant_view->addToFolder(mConversationsRoot);
+ participant_view->setVisible(TRUE);
+ refreshConversation();
}
- updateHeaderAndToolbar();
}
-void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata)
+void LLIMConversation::removeConversationViewParticipant(const LLUUID& participant_id)
{
- // TODO: Check this code when sort order menu will be added. (EM)
- if (!mParticipantList)
+ LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
+ if (widget)
{
- return;
+ mConversationsRoot->extractItem(widget);
+ delete widget;
+ mConversationsWidgets.erase(participant_id);
+ refreshConversation();
}
+}
- std::string chosen_item = userdata.asString();
+void LLIMConversation::updateConversationViewParticipant(const LLUUID& participant_id)
+{
+ LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
+ if (widget)
+ {
+ widget->refresh();
+ }
+ refreshConversation();
+}
- if (chosen_item == "sort_name")
+void LLIMConversation::refreshConversation()
+{
+ // Note: We collect participants names to change the session name only in the case of ad-hoc conversations
+ bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false);
+ uuid_vec_t participants_uuids; // uuids vector for building the added participants name string
+ // For P2P chat, we still need to update the session name who may have changed (switch display name for instance)
+ if (mIsP2PChat && mSession)
{
- mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME);
+ participants_uuids.push_back(mSession->mOtherParticipantID);
}
+ conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
+ while (widget_it != mConversationsWidgets.end())
+ {
+ // Add the participant to the list except if it's the agent itself (redundant)
+ if (is_ad_hoc && (widget_it->first != gAgentID))
+ {
+ participants_uuids.push_back(widget_it->first);
+ }
+ widget_it->second->refresh();
+ widget_it->second->setVisible(TRUE);
+ ++widget_it;
+ }
+ if (is_ad_hoc || mIsP2PChat)
+ {
+ // Build the session name and update it
+ std::string session_name;
+ if (participants_uuids.size() != 0)
+ {
+ LLAvatarActions::buildResidentsString(participants_uuids, session_name);
+ }
+ else
+ {
+ session_name = LLIMModel::instance().getName(mSessionID);
+ }
+ updateSessionName(session_name);
+ }
+ mConversationViewModel.requestSortAll();
+ mConversationsRoot->arrangeAll();
+ mConversationsRoot->update();
+ updateHeaderAndToolbar();
+ refresh();
+}
+
+// Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity!
+LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item)
+{
+ LLRect panel_rect = mParticipantListPanel->getRect();
+
+ LLConversationViewParticipant::Params params;
+ params.name = item->getDisplayName();
+ params.root = mConversationsRoot;
+ params.listener = item;
+ params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); // *TODO: use conversation_view_participant.xml itemHeight value in lieu of 24
+ params.tool_tip = params.name;
+ params.participant_id = item->getUUID();
+
+ return LLUICtrlFactory::create<LLConversationViewParticipant>(params);
+}
+
+void LLIMConversation::setSortOrder(const LLConversationSort& order)
+{
+ mConversationViewModel.setSorter(order);
+ mConversationsRoot->arrangeAll();
+ refreshConversation();
}
void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata)
@@ -425,6 +557,11 @@ void LLIMConversation::hideOrShowTitle()
floater_contents->setShape(contents_rect);
}
+void LLIMConversation::updateSessionName(const std::string& name)
+{
+ mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name);
+}
+
void LLIMConversation::hideAllStandardButtons()
{
for (S32 i = 0; i < BUTTON_COUNT; i++)
@@ -582,7 +719,7 @@ void LLIMConversation::onTearOffClicked()
mSaveRect = isTornOff();
initRectControl();
LLFloater::onClickTearOff(this);
- updateHeaderAndToolbar();
+ refreshConversation();
}
// static
@@ -599,7 +736,7 @@ bool LLIMConversation::checkIfTornOff()
if (isTorn != isTornOff())
{
setTornOff(isTorn);
- updateHeaderAndToolbar();
+ refreshConversation();
}
return isTorn;
diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h
index d1e2bfff55..93a1ab847e 100644
--- a/indra/newview/llimconversation.h
+++ b/indra/newview/llimconversation.h
@@ -35,6 +35,8 @@
#include "lleventtimer.h"
#include "llimview.h"
#include "llconversationmodel.h"
+#include "llconversationview.h"
+#include "lltexteditor.h"
class LLPanelChatControlPanel;
class LLChatEntry;
@@ -80,7 +82,16 @@ public:
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setFocus(BOOL focus);
-
+
+ // Handle the left hand participant list widgets
+ void addConversationViewParticipant(LLConversationItem* item);
+ void removeConversationViewParticipant(const LLUUID& participant_id);
+ void updateConversationViewParticipant(const LLUUID& participant_id);
+ void refreshConversation();
+ void buildConversationViewParticipant();
+
+ void setSortOrder(const LLConversationSort& order);
+
virtual void updateMessages() {}
protected:
@@ -100,15 +111,15 @@ protected:
// refresh a visual state of the Call button
void updateCallBtnState(bool callIsActive);
- void buildParticipantList();
- void onSortMenuItemClicked(const LLSD& userdata);
-
void hideOrShowTitle(); // toggle the floater's drag handle
void hideAllStandardButtons();
/// Update floater header and toolbar buttons when hosted/torn off state is toggled.
void updateHeaderAndToolbar();
+ // Update the input field help text and other places that need the session name
+ virtual void updateSessionName(const std::string& name);
+
// set the enable/disable state for the Call button
virtual void enableDisableCallBtn();
@@ -126,10 +137,15 @@ protected:
LLIMModel::LLIMSession* mSession;
- LLLayoutPanel* mParticipantListPanel;
- LLParticipantList* mParticipantList;
- LLUUID mSessionID;
+ // Participants list: model and view
+ LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
+
+ LLUUID mSessionID;
+ LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel
+ LLParticipantList* getParticipantList();
+ conversations_widgets_map mConversationsWidgets;
LLConversationViewModel mConversationViewModel;
+ LLFolderView* mConversationsRoot;
LLChatHistory* mChatHistory;
LLChatEntry* mInputEditor;
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 2ff883da67..73c7be37eb 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -220,7 +220,6 @@ void LLIMFloater::sendMsg(const std::string& msg)
LLIMFloater::~LLIMFloater()
{
- mParticipantsListRefreshConnection.disconnect();
mVoiceChannelStateChangeConnection.disconnect();
if(LLVoiceClient::instanceExists())
{
@@ -243,7 +242,6 @@ void LLIMFloater::initIMSession(const LLUUID& session_id)
{
mIsP2PChat = mSession->isP2PSessionType();
mSessionInitialized = mSession->mSessionInitialized;
-
mDialog = mSession->mType;
}
}
@@ -271,31 +269,10 @@ void LLIMFloater::initIMFloater()
mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
}
- if (mIsP2PChat)
- {
- // look up display name for window title
- LLAvatarNameCache::get(mSession->mOtherParticipantID,
- boost::bind(&LLIMFloater::onAvatarNameCache,
- this, _1, _2));
- }
- else
+ if (!mIsP2PChat)
{
std::string session_name(LLIMModel::instance().getName(mSessionID));
- updateSessionName(session_name, session_name);
-
- // For ad hoc conferences we should update the title with participants names.
- if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID))
- || mDialog == IM_SESSION_CONFERENCE_START)
- {
- if (mParticipantsListRefreshConnection.connected())
- {
- mParticipantsListRefreshConnection.disconnect();
- }
-
- LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list");
- mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback(
- boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1));
- }
+ updateSessionName(session_name);
}
}
@@ -525,64 +502,13 @@ void LLIMFloater::onVoiceChannelStateChanged(
updateCallBtnState(callIsActive);
}
-void LLIMFloater::updateSessionName(const std::string& ui_title,
- const std::string& ui_label)
-{
- mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label);
- setTitle(ui_title);
-}
-
-void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
- const LLAvatarName& av_name)
-{
- // Use display name only for labels, as the extended name will be in the
- // floater title
- std::string ui_title = av_name.getCompleteName();
- updateSessionName(ui_title, av_name.mDisplayName);
- mTypingStart.setArg("[NAME]", ui_title);
-}
-
-void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)
+void LLIMFloater::updateSessionName(const std::string& name)
{
- LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl);
- if (!avatar_list)
- {
- return;
- }
-
- bool all_names_resolved = true;
- std::vector<LLSD> participants_uuids;
- uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string
-
- avatar_list->getValues(participants_uuids);
-
- // Check whether we have all participants names in LLAvatarNameCache
- for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it)
- {
- const LLUUID& id = it->asUUID();
- temp_uuids.push_back(id);
- LLAvatarName av_name;
- if (!LLAvatarNameCache::get(id, &av_name))
- {
- all_names_resolved = false;
-
- // If a name is not found in cache, request it and continue the process recursively
- // until all ids are resolved into names.
- LLAvatarNameCache::get(id,
- boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list));
- break;
- }
- }
-
- if (all_names_resolved)
- {
- std::string ui_title;
- LLAvatarActions::buildResidentsString(temp_uuids, ui_title);
- updateSessionName(ui_title, ui_title);
- }
+ LLIMConversation::updateSessionName(name);
+ setTitle(name);
+ mTypingStart.setArg("[NAME]", name);
}
-
//static
LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
{
@@ -771,8 +697,7 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
if (mSessionID != im_session_id)
{
initIMSession(im_session_id);
-
- buildParticipantList();
+ buildConversationViewParticipant();
}
initIMFloater();
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 1fae3cff50..6ba31657dc 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -137,15 +137,8 @@ private:
/*virtual*/ void onClickCloseBtn();
- // Update the window title, input field help text, etc.
- void updateSessionName(const std::string& ui_title, const std::string& ui_label);
-
- // For display name lookups for IM window titles
- void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
-
- /// Updates the list of ad hoc conference participants
- /// in an IM floater title.
- void onParticipantsListChanged(LLUICtrl* ctrl);
+ // Update the window title and input field help text
+ /*virtual*/ void updateSessionName(const std::string& name);
bool dropPerson(LLUUID* person_id, bool drop);
@@ -198,8 +191,6 @@ private:
// connection to voice channel state change signal
boost::signals2::connection mVoiceChannelStateChangeConnection;
-
- boost::signals2::connection mParticipantsListRefreshConnection;
};
#endif // LL_IMFLOATER_H
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index df2491acbd..9c1f5d7593 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -98,8 +98,8 @@ LLIMFloaterContainer::~LLIMFloaterContainer()
void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{
- LLIMConversation::addToHost(session_id);
addConversationListItem(session_id);
+ LLIMConversation::addToHost(session_id);
}
void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
@@ -109,12 +109,13 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std:
void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id)
{
- LLIMConversation::addToHost(session_id);
addConversationListItem(session_id);
+ LLIMConversation::addToHost(session_id);
}
void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
+ // *TODO: We should do this *without* delete and recreate
addConversationListItem(new_session_id, removeConversationListItem(old_session_id));
}
@@ -385,7 +386,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)
// For debug only
//std::ostringstream llsd_value;
//llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl;
- //llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl;
+ //llinfos << "LLIMFloaterContainer::onConversationModelEvent, event = " << llsd_value.str() << llendl;
// end debug
// Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that
@@ -399,16 +400,18 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)
LLUUID session_id = event.get("session_uuid").asUUID();
LLUUID participant_id = event.get("participant_uuid").asUUID();
- LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]);
+ LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,session_id));
if (!session_view)
{
- // We skip events that are not associated to a session
+ // We skip events that are not associated with a session
return false;
}
LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id);
+ LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id)));
if (type == "remove_participant")
{
+ // Remove a participant view from the hierarchical conversation list
if (participant_view)
{
session_view->extractItem(participant_view);
@@ -416,41 +419,52 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)
session_view->refresh();
mConversationsRoot->arrangeAll();
}
+ // Remove a participant view from the conversation floater
+ if (conversation_floater)
+ {
+ conversation_floater->removeConversationViewParticipant(participant_id);
+ }
}
else if (type == "add_participant")
{
- if (!participant_view)
+ LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]);
+ LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL);
+ if (!participant_view && session_model && participant_model)
{
- LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]);
- if (session_model)
+ LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
+ if (session_id.isNull() || (im_sessionp && !im_sessionp->isP2PSessionType()))
{
- const LLUUID& uuid = session_model->getUUID();
-
- LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(uuid);
-
- if (uuid.isNull() || im_sessionp && !im_sessionp->isP2PSessionType())
- {
- LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id);
- if (participant_model)
- {
- participant_view = createConversationViewParticipant(participant_model);
- participant_view->addToFolder(session_view);
- participant_view->setVisible(TRUE);
- }
- }
+ participant_view = createConversationViewParticipant(participant_model);
+ participant_view->addToFolder(session_view);
+ participant_view->setVisible(TRUE);
}
}
+ // Add a participant view to the conversation floater
+ if (conversation_floater && participant_model)
+ {
+ conversation_floater->addConversationViewParticipant(participant_model);
+ }
}
else if (type == "update_participant")
{
+ // Update the participant view in the hierarchical conversation list
if (participant_view)
{
participant_view->refresh();
}
+ // Update the participant view in the conversation floater
+ if (conversation_floater)
+ {
+ conversation_floater->updateConversationViewParticipant(participant_id);
+ }
}
else if (type == "update_session")
{
session_view->refresh();
+ if (conversation_floater)
+ {
+ conversation_floater->refreshConversation();
+ }
}
mConversationViewModel.requestSortAll();
@@ -754,6 +768,19 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order)
mConversationsRoot->arrangeAll();
// try to keep selection onscreen, even if it wasn't to start with
mConversationsRoot->scrollToShowSelection();
+
+ // Notify all conversation (torn off or not) of the change to the sort order
+ // Note: For the moment, the sort order is *unique* across all conversations. That might change in the future.
+ for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++)
+ {
+ LLUUID session_id = it_session->first;
+ LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id)));
+ if (conversation_floater)
+ {
+ conversation_floater->setSortOrder(order);
+ }
+ }
+
gSavedSettings.setU32("ConversationSortOrder", (U32)order);
}
@@ -1081,10 +1108,10 @@ void LLIMFloaterContainer::showConversation(const LLUUID& session_id)
selectConversation(session_id);
}
-//Will select only the conversation item
+// Will select only the conversation item
void LLIMFloaterContainer::selectConversation(const LLUUID& session_id)
{
- LLFolderViewItem* widget = mConversationsWidgets[session_id];
+ LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id);
if (widget)
{
(widget->getRoot())->setSelection(widget, FALSE, FALSE);
@@ -1135,63 +1162,55 @@ BOOL LLIMFloaterContainer::selectConversationPair(const LLUUID& session_id, bool
void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id)
{
- conversations_items_map::iterator item_it = mConversationsItems.find(session_id);
- if (item_it != mConversationsItems.end())
+ LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id));
+ if (item)
{
- LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second);
- if (item)
- {
- item->setTimeNow(participant_id);
- mConversationViewModel.requestSortAll();
- mConversationsRoot->arrangeAll();
- }
+ item->setTimeNow(participant_id);
+ mConversationViewModel.requestSortAll();
+ mConversationsRoot->arrangeAll();
}
}
void LLIMFloaterContainer::setNearbyDistances()
{
- // Get the nearby chat session: that's the one with uuid nul in mConversationsItems
- conversations_items_map::iterator item_it = mConversationsItems.find(LLUUID());
- if (item_it != mConversationsItems.end())
- {
- LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second);
- if (item)
+ // Get the nearby chat session: that's the one with uuid nul
+ LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,LLUUID()));
+ if (item)
+ {
+ // Get the positions of the nearby avatars and their ids
+ std::vector<LLVector3d> positions;
+ uuid_vec_t avatar_ids;
+ LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
+ // Get the position of the agent
+ const LLVector3d& me_pos = gAgent.getPositionGlobal();
+ // For each nearby avatar, compute and update the distance
+ int avatar_count = positions.size();
+ for (int i = 0; i < avatar_count; i++)
{
- // Get the positions of the nearby avatars and their ids
- std::vector<LLVector3d> positions;
- uuid_vec_t avatar_ids;
- LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
- // Get the position of the agent
- const LLVector3d& me_pos = gAgent.getPositionGlobal();
- // For each nearby avatar, compute and update the distance
- int avatar_count = positions.size();
- for (int i = 0; i < avatar_count; i++)
- {
- F64 dist = dist_vec_squared(positions[i], me_pos);
- item->setDistance(avatar_ids[i],dist);
- }
- // Also does it for the agent itself
- item->setDistance(gAgent.getID(),0.0f);
- // Request resort
- mConversationViewModel.requestSortAll();
- mConversationsRoot->arrangeAll();
+ F64 dist = dist_vec_squared(positions[i], me_pos);
+ item->setDistance(avatar_ids[i],dist);
}
+ // Also does it for the agent itself
+ item->setDistance(gAgent.getID(),0.0f);
+ // Request resort
+ mConversationViewModel.requestSortAll();
+ mConversationsRoot->arrangeAll();
}
}
-void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/)
+LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/)
{
bool is_nearby_chat = uuid.isNull();
- //Stores the display name for the conversation line item
+ // Stores the display name for the conversation line item
std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid);
- // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do)
+ // Check if the item is not already in the list, exit (nothing to do)
// Note: this happens often, when reattaching a torn off conversation for instance
conversations_items_map::iterator item_it = mConversationsItems.find(uuid);
if (item_it != mConversationsItems.end())
{
- return;
+ return item_it->second;
}
// Remove the conversation item that might exist already: it'll be recreated anew further down anyway
@@ -1203,12 +1222,12 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi
LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid));
if (speaker_manager)
{
- item = new LLParticipantList(speaker_manager, NULL, getRootViewModel(), true, false);
+ item = new LLParticipantList(speaker_manager, getRootViewModel());
}
if (!item)
{
llwarns << "Couldn't create conversation session item : " << display_name << llendl;
- return;
+ return NULL;
}
item->renameItem(display_name);
item->updateParticipantName(NULL);
@@ -1239,6 +1258,12 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi
current_participant_model++;
}
}
+ // Do that too for the conversation dialog
+ LLIMConversation *conversation_floater = (uuid.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(uuid)));
+ if (conversation_floater)
+ {
+ conversation_floater->buildConversationViewParticipant();
+ }
// set the widget to minimized mode if conversations pane is collapsed
widget->toggleMinimizedMode(mConversationsPane->isCollapsed());
@@ -1250,7 +1275,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi
mConversationsRoot->scrollToShowSelection();
}
- return;
+ return item;
}
bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus)
@@ -1260,20 +1285,16 @@ bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c
// the widget will also delete its listener
bool isWidgetSelected = false;
LLFolderViewItem* new_selection = NULL;
- conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid);
- if (widget_it != mConversationsWidgets.end())
+ LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
+ if (widget)
{
- LLFolderViewItem* widget = widget_it->second;
- if (widget)
+ isWidgetSelected = widget->isSelected();
+ new_selection = mConversationsRoot->getNextFromChild(widget);
+ if(new_selection == NULL)
{
- isWidgetSelected = widget->isSelected();
- new_selection = mConversationsRoot->getNextFromChild(widget);
- if(new_selection == NULL)
- {
- new_selection = mConversationsRoot->getPreviousFromChild(widget);
- }
- widget->destroyView();
+ new_selection = mConversationsRoot->getPreviousFromChild(widget);
}
+ widget->destroyView();
}
// Suppress the conversation items and widgets from their respective maps
@@ -1315,9 +1336,6 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti
LLRect panel_rect = mConversationsListPanel->getRect();
params.name = item->getDisplayName();
- //params.icon = bridge->getIcon();
- //params.icon_open = bridge->getOpenIcon();
- //params.creation_date = bridge->getCreationDate();
params.root = mConversationsRoot;
params.listener = item;
@@ -1325,7 +1343,8 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti
params.rect = LLRect (0, 24, panel_rect.getWidth(), 0);
params.tool_tip = params.name;
params.participant_id = item->getUUID();
-
+ params.folder_indentation = 42;
+
return LLUICtrlFactory::create<LLConversationViewParticipant>(params);
}
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
index 691bc39811..e42ed053cb 100644
--- a/indra/newview/llimfloatercontainer.h
+++ b/indra/newview/llimfloatercontainer.h
@@ -93,6 +93,8 @@ public:
LLConversationViewModel& getRootViewModel() { return mConversationViewModel; }
LLUUID getSelectedSession() { return mSelectedSession; }
void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; }
+ LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); }
+ LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); }
void onNearbyChatClosed();
@@ -155,7 +157,7 @@ private:
// Conversation list implementation
public:
bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true);
- void addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false);
+ LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false);
void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id);
void setNearbyDistances();
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index e199cb5776..9a4d1166db 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -1,6 +1,6 @@
/**
* @file llparticipantlist.cpp
- * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages
+ * @brief LLParticipantList : model of a conversation session with added speaker events handling
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -26,45 +26,17 @@
#include "llviewerprecompiledheaders.h"
-// common includes
-#include "lltrans.h"
-#include "llavataractions.h"
#include "llavatarnamecache.h"
-#include "llavatarname.h"
-#include "llagent.h"
-
#include "llimview.h"
#include "llimfloatercontainer.h"
-#include "llpanelpeoplemenus.h"
-#include "llnotificationsutil.h"
#include "llparticipantlist.h"
#include "llspeakers.h"
-#include "llviewercontrol.h"
-#include "llviewermenu.h"
-#include "llvoiceclient.h"
//LLParticipantList retrieves add, clear and remove events and updates view accordingly
#if LL_MSVC
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
-static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR;
-
-// helper function to update AvatarList Item's indicator in the voice participant list
-static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted)
-{
- if (avatar_list)
- {
- LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid));
- if (item)
- {
- LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator");
- indicator->setIsMuted(is_muted);
- }
- }
-}
-
-
// See EXT-4301.
/**
* class LLAvalineUpdater - observe the list of voice participants in session and check
@@ -204,16 +176,9 @@ private:
uuid_set_t mAvalineCallers;
};
-LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
- LLAvatarList* avatar_list,
- LLFolderViewModelInterface& root_view_model,
- bool use_context_menu/* = true*/,
- bool exclude_agent /*= true*/,
- bool can_toggle_icons /*= true*/) :
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLFolderViewModelInterface& root_view_model) :
LLConversationItemSession(data_source->getSessionID(), root_view_model),
mSpeakerMgr(data_source),
- mAvatarList(avatar_list),
- mExcludeAgent(exclude_agent),
mValidateSpeakerCallback(NULL)
{
@@ -234,32 +199,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
mSpeakerMgr->addListener(mSpeakerUpdateListener, "update_speaker");
setSessionID(mSpeakerMgr->getSessionID());
-
- if (mAvatarList)
- {
- mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
- LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL;
- mAvatarList->setSessionID(mSpeakerMgr->getSessionID());
- mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1));
- mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2));
- // Set onAvatarListDoubleClicked as default on_return action.
- mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));
-
- if (use_context_menu)
- {
- mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
- }
- else
- {
- mAvatarList->setContextMenu(NULL);
- }
-
- if (use_context_menu && can_toggle_icons)
- {
- mAvatarList->setShowIcons("ParticipantListShowIcons");
- mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList));
- }
- }
//Lets fill avatarList with existing speakers
LLSpeakerMgr::speaker_list_t speaker_list;
@@ -278,8 +217,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
mModeratorToRemoveList.insert(speakerp->mID);
}
}
- // we need to exclude agent id for non group chat
- sort();
// Identify and store what kind of session we are
LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(data_source->getSessionID());
@@ -305,129 +242,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
LLParticipantList::~LLParticipantList()
{
- if (mAvatarList)
- {
- mAvatarListDoubleClickConnection.disconnect();
- mAvatarListRefreshConnection.disconnect();
- mAvatarListReturnConnection.disconnect();
- mAvatarListToggleIconsConnection.disconnect();
- }
-
- if (mAvatarList)
- {
- mAvatarList->setContextMenu(NULL);
- mAvatarList->setComparator(NULL);
- }
-
delete mAvalineUpdater;
}
-void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
-{
- if (mAvatarList)
- {
- mAvatarList->setSpeakingIndicatorsVisible(visible);
- }
-}
-
-void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl)
-{
- LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl);
- if(!item)
- {
- return;
- }
-
- LLUUID clicked_id = item->getAvatarId();
-
- if (clicked_id.isNull() || clicked_id == gAgent.getID())
- return;
-
- LLAvatarActions::startIM(clicked_id);
-}
-
-void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
-{
- LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl);
- const std::string moderator_indicator(LLTrans::getString("IM_moderator_label"));
- const std::size_t moderator_indicator_len = moderator_indicator.length();
-
- // Firstly remove moderators indicator
- std::set<LLUUID>::const_iterator
- moderator_list_it = mModeratorToRemoveList.begin(),
- moderator_list_end = mModeratorToRemoveList.end();
- for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
- {
- LLAvatarListItem* item = (list ? dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)) : NULL);
- if ( item )
- {
- std::string name = item->getAvatarName();
- std::string tooltip = item->getAvatarToolTip();
- size_t found = name.find(moderator_indicator);
- if (found != std::string::npos)
- {
- name.erase(found, moderator_indicator_len);
- item->setAvatarName(name);
- }
- found = tooltip.find(moderator_indicator);
- if (found != tooltip.npos)
- {
- tooltip.erase(found, moderator_indicator_len);
- item->setAvatarToolTip(tooltip);
- }
- }
- setParticipantIsModerator(*moderator_list_it,false);
- }
-
- mModeratorToRemoveList.clear();
-
- // Add moderators indicator
- moderator_list_it = mModeratorList.begin();
- moderator_list_end = mModeratorList.end();
- for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
- {
- LLAvatarListItem* item = (list ? dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)) : NULL);
- if ( item )
- {
- std::string name = item->getAvatarName();
- std::string tooltip = item->getAvatarToolTip();
- size_t found = name.find(moderator_indicator);
- if (found == std::string::npos)
- {
- name += " ";
- name += moderator_indicator;
- item->setAvatarName(name);
- }
- found = tooltip.find(moderator_indicator);
- if (found == std::string::npos)
- {
- tooltip += " ";
- tooltip += moderator_indicator;
- item->setAvatarToolTip(tooltip);
- }
- }
- setParticipantIsModerator(*moderator_list_it,true);
- }
-
- // update voice mute state of all items. See EXT-7235
- LLSpeakerMgr::speaker_list_t speaker_list;
-
- // Use also participants which are not in voice session now (the second arg is TRUE).
- // They can already have mModeratorMutedVoice set from the previous voice session
- // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time.
- mSpeakerMgr->getSpeakerList(&speaker_list, TRUE);
- for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
- {
- const LLPointer<LLSpeaker>& speakerp = *it;
-
- if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
- {
- setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice);
- update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice);
- }
- }
-}
-
/*
Seems this method is not necessary after onAvalineCallerRemoved was implemented;
@@ -441,40 +258,11 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
*/
void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id)
{
- if (mAvatarList)
- {
- LLPanel* item = mAvatarList->getItemByValue(participant_id);
-
- if (NULL == item)
- {
- LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL;
- return;
- }
-
- if (typeid(*item) == typeid(LLAvalineListItem))
- {
- LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL;
- // item representing an Avaline caller has a correct type already.
- return;
- }
-
- LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL;
-
- // remove UUID from LLAvatarList::mIDs to be able add it again.
- uuid_vec_t& ids = mAvatarList->getIDs();
- uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id);
- ids.erase(pos);
-
- // remove item directly
- mAvatarList->removeItem(item);
- }
-
LLConversationItemParticipant* participant = findParticipant(participant_id);
if (participant)
{
removeParticipant(participant);
}
-
// re-add avaline caller with a correct class instance.
addAvatarIDExceptAgent(participant_id);
}
@@ -486,23 +274,6 @@ void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id)
mSpeakerMgr->removeAvalineSpeaker(participant_id);
}
-void LLParticipantList::setSortOrder(EParticipantSortOrder order)
-{
- const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
-
- if ( speaker_sort_order != order )
- {
- gSavedSettings.setU32("SpeakerParticipantDefaultOrder", (U32)order);
- sort();
- }
-}
-
-const LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() const
-{
- const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
- return EParticipantSortOrder(speaker_sort_order);
-}
-
void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)
{
mValidateSpeakerCallback = cb;
@@ -511,20 +282,6 @@ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t c
void LLParticipantList::update()
{
mSpeakerMgr->update(true);
-
- // Need to resort the participant list if it's in sort by recent speaker order.
- if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered())
- {
- // Resort avatar list
- sort();
- }
-}
-
-bool LLParticipantList::isHovered()
-{
- S32 x, y;
- LLUI::getMousePositionScreen(&x, &y);
- return (mAvatarList ? mAvatarList->calcScreenRect().pointInRect(x, y) : false);
}
bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
@@ -537,35 +294,18 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co
}
addAvatarIDExceptAgent(uu_id);
- sort();
return true;
}
bool LLParticipantList::onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
LLUUID avatar_id = event->getValue().asUUID();
- if (mAvatarList)
- {
- uuid_vec_t& group_members = mAvatarList->getIDs();
- uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), avatar_id);
- if(pos != group_members.end())
- {
- group_members.erase(pos);
- mAvatarList->setDirty();
- }
- }
removeParticipant(avatar_id);
return true;
}
bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
- if (mAvatarList)
- {
- uuid_vec_t& group_members = mAvatarList->getIDs();
- group_members.clear();
- mAvatarList->setDirty();
- }
clearParticipants();
return true;
}
@@ -605,9 +345,7 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> e
mModeratorList.erase(id);
}
}
-
- // apply changes immediately
- onAvatarListRefreshed(mAvatarList, LLSD());
+ // *TODO : do we have to fire an event so that LLIMConversation::refreshConversation() gets called
}
}
return true;
@@ -622,48 +360,13 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event
if (event->getValue().asString() == "voice")
{
setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice);
- update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice);
}
return true;
}
-void LLParticipantList::sort()
-{
- // *TODO : Merov : Need to plan for sort() for LLConversationModel
- if ( !mAvatarList )
- return;
-
- switch ( getSortOrder() )
- {
- case E_SORT_BY_NAME :
- // if mExcludeAgent == true , then no need to keep agent on top of the list
- if(mExcludeAgent)
- {
- mAvatarList->sortByName();
- }
- else
- {
- mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR);
- mAvatarList->sort();
- }
- break;
- case E_SORT_BY_RECENT_SPEAKERS:
- if (mSortByRecentSpeakers.isNull())
- mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this);
- mAvatarList->setComparator(mSortByRecentSpeakers.get());
- mAvatarList->sort();
- break;
- default :
- llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
- return;
- }
-}
-
void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
{
// Do not add if already in there or excluded for some reason
- if (mExcludeAgent && gAgent.getID() == avatar_id) return;
- if (mAvatarList && mAvatarList->contains(avatar_id)) return;
if (findParticipant(avatar_id)) return;
bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id);
@@ -677,25 +380,16 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name);
participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel);
participant->fetchAvatarName();
- if (mAvatarList)
- {
- mAvatarList->getIDs().push_back(avatar_id);
- mAvatarList->setDirty();
- }
}
else
{
std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id);
// Create a participant view model instance
participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel);
- if (mAvatarList)
- {
- mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name);
- }
mAvalineUpdater->watchAvalineCaller(avatar_id);
}
- // *TODO : Merov : need to update the online/offline status of the participant.
+ // *TODO : Need to update the online/offline status of the participant
// Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id))
// Add the participant model to the session's children list
@@ -768,33 +462,4 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::
return mParent.onSpeakerMuteEvent(event, userdata);
}
-bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
-{
- if (mParent.mSpeakerMgr)
- {
- LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId());
- LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId());
- if ( lhs.notNull() && rhs.notNull() )
- {
- // Compare by last speaking time
- if( lhs->mLastSpokeTime != rhs->mLastSpokeTime )
- return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime );
- else if ( lhs->mSortIndex != rhs->mSortIndex )
- return ( lhs->mSortIndex < rhs->mSortIndex );
- }
- else if ( lhs.notNull() )
- {
- // True if only avatar_item1 speaker info available
- return true;
- }
- else if ( rhs.notNull() )
- {
- // False if only avatar_item2 speaker info available
- return false;
- }
- }
- // By default compare by name.
- return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2);
-}
-
//EOF
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index aaf1e070a5..3a3ae76604 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -1,6 +1,6 @@
/**
* @file llparticipantlist.h
- * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages
+ * @brief LLParticipantList : model of a conversation session with added speaker events handling
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -28,13 +28,9 @@
#define LL_PARTICIPANTLIST_H
#include "llviewerprecompiledheaders.h"
-#include "llevent.h"
-#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator
-#include "lllistcontextmenu.h"
#include "llconversationmodel.h"
class LLSpeakerMgr;
-class LLAvatarList;
class LLUICtrl;
class LLAvalineUpdater;
@@ -45,20 +41,8 @@ public:
typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
- LLParticipantList(LLSpeakerMgr* data_source,
- LLAvatarList* avatar_list,
- LLFolderViewModelInterface& root_view_model,
- bool use_context_menu = true,
- bool exclude_agent = true,
- bool can_toggle_icons = true);
+ LLParticipantList(LLSpeakerMgr* data_source, LLFolderViewModelInterface& root_view_model);
~LLParticipantList();
- void setSpeakingIndicatorsVisible(BOOL visible);
-
- enum EParticipantSortOrder
- {
- E_SORT_BY_NAME = 0,
- E_SORT_BY_RECENT_SPEAKERS = 1,
- };
/**
* Adds specified avatar ID to the existing list if it is not Agent's ID
@@ -68,12 +52,6 @@ public:
void addAvatarIDExceptAgent(const LLUUID& avatar_id);
/**
- * Set and sort Avatarlist by given order
- */
- void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
- const EParticipantSortOrder getSortOrder() const;
-
- /**
* Refreshes the participant list.
*/
void update();
@@ -99,11 +77,6 @@ protected:
bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
/**
- * Sorts the Avatarlist by stored order
- */
- void sort();
-
- /**
* List of listeners implementing LLOldEvents::LLSimpleListener.
* There is no way to handle all the events in one listener as LLSpeakerMgr registers
* listeners in such a way that one listener can handle only one type of event
@@ -159,25 +132,7 @@ protected:
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
};
- /**
- * Comparator for comparing avatar items by last spoken time
- */
- class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount
- {
- LOG_CLASS(LLAvatarItemRecentSpeakerComparator);
- public:
- LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){};
- virtual ~LLAvatarItemRecentSpeakerComparator() {};
- protected:
- virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
- private:
- LLParticipantList& mParent;
- };
-
private:
- void onAvatarListDoubleClicked(LLUICtrl* ctrl);
- void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
-
void onAvalineCallerFound(const LLUUID& participant_id);
void onAvalineCallerRemoved(const LLUUID& participant_id);
@@ -188,10 +143,7 @@ private:
*/
void adjustParticipant(const LLUUID& speaker_id);
- bool isHovered();
-
LLSpeakerMgr* mSpeakerMgr;
- LLAvatarList* mAvatarList;
std::set<LLUUID> mModeratorList;
std::set<LLUUID> mModeratorToRemoveList;
@@ -203,20 +155,6 @@ private:
LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
- /**
- * This field manages an adding a new avatar_id in the mAvatarList
- * If true, then agent_id wont be added into mAvatarList
- * Also by default this field is controlling a sort procedure, @c sort()
- */
- bool mExcludeAgent;
-
- // boost::connections
- boost::signals2::connection mAvatarListDoubleClickConnection;
- boost::signals2::connection mAvatarListRefreshConnection;
- boost::signals2::connection mAvatarListReturnConnection;
- boost::signals2::connection mAvatarListToggleIconsConnection;
-
- LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
validate_speaker_callback_t mValidateSpeakerCallback;
LLAvalineUpdater* mAvalineUpdater;
};
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index a4d45e1fb8..b99d04abae 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -32,7 +32,6 @@
#include "llviewerfloaterreg.h"
#include "llfloaterautoreplacesettings.h"
#include "llcompilequeue.h"
-#include "llcallfloater.h"
#include "llfasttimerview.h"
#include "llfloaterabout.h"
#include "llfloaterauction.h"
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 412e4593bc..3a26f14772 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -3715,8 +3715,7 @@ void LLVivoxVoiceClient::participantUpdatedEvent(
voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager
and event is not fired.
- So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it
- in LLCallFloater::draw()
+ So, we have to call LLSpeakerMgr::update() here.
*/
LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 2b542595c5..a889eb7933 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -14,7 +14,7 @@
width="394"
can_resize="true"
can_tear_off="false"
- min_width="250"
+ min_width="340"
min_height="190"
positioning="relative">
<floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string>
@@ -157,19 +157,8 @@
min_width="115"
width="150"
height="310"
- auto_resize="false">
- <avatar_list
- color="DkGray2"
- follows="all"
- height="310"
- ignore_online_status="true"
- layout="topleft"
- name="speakers_list"
- opaque="false"
- show_info_btn="true"
- show_profile_btn="false"
- show_speaking_indicator="false"
- width="150" />
+ user_resize="true"
+ auto_resize="true">
</layout_panel>
<layout_panel
default_tab_group="3"
@@ -183,7 +172,8 @@
user_resize="true"
auto_resize="true"
visible="true"
- name="left_part_holder">
+ name="left_part_holder"
+ min_width="225">
<panel
name="trnsAndChat_panel"
follows="all"
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
deleted file mode 100644
index dce2720cf8..0000000000
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- positioning="cascading"
- can_resize="true"
- can_minimize="true"
- can_close="true"
- chrome="true"
- height="205"
- layout="topleft"
- min_height="124"
- min_width="190"
- name="floater_voice_controls"
- help_topic="floater_voice_controls"
- title="VOICE CONTROLS"
- save_dock_state="true"
- save_visibility="true"
- save_rect="true"
- single_instance="true"
- width="282">
- <string
- name="title_nearby">
- VOICE SETTINGS
- </string>
- <string
- name="title_group">
- GROUP CALL WITH [GROUP]
- </string>
- <string
- name="title_adhoc">
- CONFERENCE CALL
- </string>
- <string
- name="title_peer_2_peer">
- CALL WITH [NAME]
- </string>
- <string
- name="no_one_near">
- No one near has voice enabled
- </string>
- <layout_stack
- clip="false"
- follows="all"
- height="189"
- layout="topleft"
- left="10"
- mouse_opaque="false"
- name="my_call_stack"
- orientation="vertical"
- width="263">
- <layout_panel
- follows="top|left|right"
- auto_resize="false"
- layout="topleft"
- min_height="20"
- height="20"
- name="my_panel">
- <avatar_icon
- enabled="false"
- follows="left|top"
- height="18"
- default_icon_name="Generic_Person"
- layout="topleft"
- left="5"
- name="user_icon"
- top="0"
- width="18" />
- <text
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="16"
- layout="topleft"
- left_pad="10"
- name="user_text"
- text_color="White"
- top="4"
- use_ellipses="true"
- value="My Avatar:"
- width="210" />
- <output_monitor
- auto_update="true"
- draw_border="false"
- follows="top|right"
- height="16"
- layout="topleft"
- right="-3"
- name="speaking_indicator"
- left_pad="5"
- visible="true"
- width="20" />
- </layout_panel>
- <layout_panel name="leave_call_panel" height="26" min_height="26" auto_resize="false">
- <layout_stack
- clip="true"
- follows="left|top|right"
- height="26"
- layout="topleft"
- mouse_opaque="false"
- name="voice_effect_and_leave_call_stack"
- orientation="horizontal"
- width="262">
- <layout_panel
- height="26"
- width="200">
- <panel
- class="panel_voice_effect"
- name="panel_voice_effect"
- visiblity_control="VoiceMorphingEnabled"
- filename="panel_voice_effect.xml" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|right"
- height="23"
- visible="true"
- layout="topleft"
- name="leave_call_btn_panel"
- width="100">
- <button
- follows="right|top"
- height="23"
- label="Leave Call"
- name="leave_call_btn"
- width="100" />
- </layout_panel>
- </layout_stack>
- </layout_panel>
- <layout_panel
- follows="all"
- layout="topleft"
- left="2"
- top_pad="0"
- height="132"
- name="callers_panel"
- auto_resize="true"
- width="280">
- <avatar_list
- follows="all"
- height="132"
- ignore_online_status="true"
- layout="topleft"
- multi_select="true"
- name="speakers_list"
- width="280" />
- <panel
- filename="panel_avatar_list_item.xml"
- follows="left|right|top"
- height="24"
- layout="topleft"
- left="0"
- name="non_avatar_caller"
- top="10"
- width="276" />
- </layout_panel>
- </layout_stack>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml
index 67feade9a3..a054e71e34 100644
--- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml
@@ -90,7 +90,7 @@
layout="topleft"
left_pad="5"
mouse_opaque="true"
- name="speaking_indicatorn"
+ name="speaking_indicator"
visible="false"
width="20" />
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml
index 0024decd4c..b83d9122f7 100755
--- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml
+++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<conversation_view_participant
folder_arrow_image="Folder_Arrow"
- folder_indentation="0"
item_height="24"
item_top_pad="0"
selection_image="Rounded_Square"
@@ -20,7 +19,6 @@
height="20"
default_icon_name="Generic_Person"
layout="topleft"
- left="50"
top="2"
width="20" />
<info_button