From c285f59ce2a05703e3a1232fcaf3ee3aea714b3f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 18 Feb 2024 12:52:19 +0100 Subject: Replace BOOL with bool in llwindow and dependent classes --- indra/newview/llconversationview.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra/newview/llconversationview.cpp') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 48c7df40df..884d9376ec 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -320,10 +320,10 @@ void LLConversationViewSession::draw() LLView::draw(); } -BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) +bool LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) { //Will try to select a child node and then itself (if a child was not selected) - BOOL result = LLFolderViewFolder::handleMouseDown(x, y, mask); + bool result = LLFolderViewFolder::handleMouseDown(x, y, mask); //This node (conversation) was selected and a child (participant) was not if(result && getRoot()) @@ -349,9 +349,9 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) return result; } -BOOL LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) +bool LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) { - BOOL result = LLFolderViewFolder::handleMouseUp(x, y, mask); + bool result = LLFolderViewFolder::handleMouseUp(x, y, mask); LLFloater* volume_floater = LLFloaterReg::findInstance("floater_voice_volume"); LLFloater* chat_volume_floater = LLFloaterReg::findInstance("chat_voice"); @@ -372,9 +372,9 @@ BOOL LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) return result; } -BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask ) +bool LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); + bool result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); if(result) { @@ -763,9 +763,9 @@ void LLConversationViewParticipant::onInfoBtnClick() LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); } -BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) +bool LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) { - BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); + bool result = LLFolderViewItem::handleMouseDown(x, y, mask); if(result && getRoot()) { -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llconversationview.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/llconversationview.cpp') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 884d9376ec..5e18f7e045 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -204,7 +204,7 @@ bool LLConversationViewSession::isHighlightActive() return (mFlashStateOn ? (mFlashTimer->isFlashingInProgress() ? mFlashTimer->isCurrentlyHighlighted() : true) : mIsCurSelection); } -BOOL LLConversationViewSession::postBuild() +bool LLConversationViewSession::postBuild() { LLFolderViewItem::postBuild(); @@ -276,7 +276,7 @@ BOOL LLConversationViewSession::postBuild() refresh(); // requires vmi } - return TRUE; + return true; } void LLConversationViewSession::draw() @@ -614,7 +614,7 @@ void LLConversationViewParticipant::initFromParams(const LLConversationViewParti addChild(outputMonitor); } -BOOL LLConversationViewParticipant::postBuild() +bool LLConversationViewParticipant::postBuild() { mAvatarIcon = getChild("avatar_icon"); @@ -638,7 +638,7 @@ BOOL LLConversationViewParticipant::postBuild() LLFolderViewItem::postBuild(); refresh(); } - return TRUE; + return true; } void LLConversationViewParticipant::draw() -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llconversationview.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llconversationview.cpp') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 5e18f7e045..7e592ab468 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -284,7 +284,7 @@ void LLConversationViewSession::draw() getViewModelItem()->update(); const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams(); - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); // Indicate that flash can start (moot operation if already started, done or not flashing) startFlashing(); @@ -444,7 +444,7 @@ void LLConversationViewSession::toggleCollapsedMode(bool is_collapsed) mItemPanel->translate(mCollapsedMode ? -h_pad : h_pad, 0); } -void LLConversationViewSession::setVisibleIfDetached(BOOL visible) +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 @@ -651,7 +651,7 @@ void LLConversationViewParticipant::draw() static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); const LLFontGL* font = getLabelFontForStyle(mLabelStyle); F32 right_x = 0; -- cgit v1.2.3 From 2117f8c4ba4565eef33f139a8c38b81f3c79648f Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sun, 3 Mar 2024 15:50:35 -0800 Subject: Refactor for vivox spatial and p2p General refactoring to improve vivox spacial and p2p voice including generalizing voice info instead of just using sip uri and credentials. Voice server type is also passed around in the generalized voice info blob. --- indra/newview/llconversationview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llconversationview.cpp') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 48c7df40df..42194c9c16 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -57,7 +57,7 @@ public: : conversation(conv) {} - virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) + virtual void onChange(EStatusType status, const LLSD& channelInfo, bool proximal) { conversation->showVoiceIndicator(conversation && status != STATUS_JOINING -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llconversationview.cpp | 1772 +++++++++++++++++----------------- 1 file changed, 886 insertions(+), 886 deletions(-) (limited to 'indra/newview/llconversationview.cpp') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 0242e4d9eb..a5b2ee29c7 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -1,886 +1,886 @@ -/** - * @file llconversationview.cpp - * @brief Implementation of conversations list widgets and views - * - * $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 "llconversationview.h" - -#include -#include "llagentdata.h" -#include "llavataractions.h" -#include "llconversationmodel.h" -#include "llfloaterimsession.h" -#include "llfloaterimnearbychat.h" -#include "llfloaterimsessiontab.h" -#include "llfloaterimcontainer.h" -#include "llfloaterreg.h" -#include "llgroupiconctrl.h" -#include "lluictrlfactory.h" -#include "lltoolbarview.h" - -// -// Implementation of conversations list session widgets -// -static LLDefaultChildRegistry::Register r_conversation_view_session("conversation_view_session"); - -const LLColor4U DEFAULT_WHITE(255, 255, 255); - -class LLNearbyVoiceClientStatusObserver : public LLVoiceClientStatusObserver -{ -public: - - LLNearbyVoiceClientStatusObserver(LLConversationViewSession* conv) - : conversation(conv) - {} - - virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) - { - conversation->showVoiceIndicator(conversation - && status != STATUS_JOINING - && status != STATUS_LEFT_CHANNEL - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking()); - } - -private: - LLConversationViewSession* conversation; -}; - -LLConversationViewSession::Params::Params() : - container() -{} - -LLConversationViewSession::LLConversationViewSession(const LLConversationViewSession::Params& p): - LLFolderViewFolder(p), - mContainer(p.container), - mItemPanel(NULL), - mCallIconLayoutPanel(NULL), - mSessionTitle(NULL), - mSpeakingIndicator(NULL), - mVoiceClientObserver(NULL), - mCollapsedMode(false), - mHasArrow(true), - mIsInActiveVoiceChannel(false), - mFlashStateOn(false), - mFlashStarted(false) -{ - mFlashTimer = new LLFlashTimer(); - mAreChildrenInited = true; // inventory only -} - -LLConversationViewSession::~LLConversationViewSession() -{ - mActiveVoiceChannelConnection.disconnect(); - - if (mVoiceClientObserver) - { - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); - } - delete mVoiceClientObserver; - } - - mFlashTimer->unset(); - delete mFlashTimer; - mFlashStateOn = false; -} - -void LLConversationViewSession::destroyView() -{ - // Chat can create and parent models(listeners) to session's model before creating - // coresponding views, such participant's models normally will wait for idle cycles - // but since we are deleting session and won't be processing any more events, make - // sure unowned LLConversationItemParticipant models are removed as well. - - LLConversationItemSession* vmi = dynamic_cast(getViewModelItem()); - - // CONV_SESSION_1_ON_1 stores participants as two models that belong to views independent - // from session (nasty! These views are widgets in LLFloaterIMSessionTab, see buildConversationViewParticipant) - if (vmi && vmi->getType() != LLConversationItem::CONV_SESSION_1_ON_1) - { - // Destroy existing views - while (!mItems.empty()) - { - LLFolderViewItem *itemp = mItems.back(); - mItems.pop_back(); - - LLFolderViewModelItem* item_vmi = itemp->getViewModelItem(); - if (item_vmi) // supposed to exist - { - // unparent to remove from child list - vmi->removeChild(item_vmi); - } - itemp->destroyView(); - } - - // Not needed in scope of sessions, but just in case - while (!mFolders.empty()) - { - LLFolderViewFolder *folderp = mFolders.back(); - mFolders.pop_back(); - - LLFolderViewModelItem* folder_vmi = folderp->getViewModelItem(); - if (folder_vmi) - { - vmi->removeChild(folder_vmi); - } - folderp->destroyView(); - } - - // Now everything that is left in model(listener) is not owned by views, - // only by sessions, deparent so it won't point to soon to be dead model - vmi->clearAndDeparentModels(); - } - - LLFolderViewFolder::destroyView(); -} - -void LLConversationViewSession::setFlashState(bool flash_state) -{ - if (flash_state && !mFlashStateOn) - { - // flash chat toolbar button if scrolled out of sight (because flashing will not be visible) - if (mContainer->isScrolledOutOfSight(this)) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } - } - - mFlashStateOn = flash_state; - mFlashStarted = false; - mFlashTimer->stopFlashing(); -} - -void LLConversationViewSession::setHighlightState(bool hihglight_state) -{ - mFlashStateOn = hihglight_state; - mFlashStarted = true; - mFlashTimer->stopFlashing(); -} - -void LLConversationViewSession::startFlashing() -{ - // Need to start flashing only when "Conversations" is opened or brought on top - if (isInVisibleChain() - && mFlashStateOn - && !mFlashStarted - && ! LLFloaterReg::getTypedInstance("im_container")->isMinimized() ) - { - mFlashStarted = true; - mFlashTimer->startFlashing(); - } -} - -bool LLConversationViewSession::isHighlightAllowed() -{ - return mFlashStateOn || mIsSelected; -} - -bool LLConversationViewSession::isHighlightActive() -{ - return (mFlashStateOn ? (mFlashTimer->isFlashingInProgress() ? mFlashTimer->isCurrentlyHighlighted() : true) : mIsCurSelection); -} - -bool LLConversationViewSession::postBuild() -{ - LLFolderViewItem::postBuild(); - - mItemPanel = LLUICtrlFactory::getInstance()->createFromFile("panel_conversation_list_item.xml", NULL, LLPanel::child_registry_t::instance()); - addChild(mItemPanel); - - mCallIconLayoutPanel = mItemPanel->getChild("call_icon_panel"); - mSessionTitle = mItemPanel->getChild("conversation_title"); - - mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewSession::onCurrentVoiceSessionChanged, this, _1)); - mSpeakingIndicator = getChild("speaking_indicator"); - - LLConversationItem* vmi = dynamic_cast(getViewModelItem()); - if (vmi) - { - switch(vmi->getType()) - { - case LLConversationItem::CONV_PARTICIPANT: - case LLConversationItem::CONV_SESSION_1_ON_1: - { - LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID()); - if (session) - { - LLAvatarIconCtrl* icon = mItemPanel->getChild("avatar_icon"); - icon->setVisible(true); - icon->setValue(session->mOtherParticipantID); - mSpeakingIndicator->setSpeakerId(session->mOtherParticipantID, session->mSessionID, true); - mHasArrow = false; - } - break; - } - case LLConversationItem::CONV_SESSION_AD_HOC: - { - LLGroupIconCtrl* icon = mItemPanel->getChild("group_icon"); - icon->setVisible(true); - mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); - break; - } - case LLConversationItem::CONV_SESSION_GROUP: - { - LLGroupIconCtrl* icon = mItemPanel->getChild("group_icon"); - icon->setVisible(true); - icon->setValue(vmi->getUUID()); - mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); - break; - } - case LLConversationItem::CONV_SESSION_NEARBY: - { - LLIconCtrl* icon = mItemPanel->getChild("nearby_chat_icon"); - icon->setVisible(true); - mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); - mIsInActiveVoiceChannel = true; - if(LLVoiceClient::instanceExists()) - { - if (mVoiceClientObserver) - { - LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); - delete mVoiceClientObserver; - } - mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); - LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver); - } - break; - } - default: - break; - } - - refresh(); // requires vmi - } - - return true; -} - -void LLConversationViewSession::draw() -{ - getViewModelItem()->update(); - - const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams(); - const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); - - // Indicate that flash can start (moot operation if already started, done or not flashing) - startFlashing(); - - // draw highlight for selected items - drawHighlight(show_context, true, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); - - // Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap. - bool draw_children = getRoot() == static_cast(this) || isOpen(); - - // Todo/fix this: arrange hides children 'out of bonds', session 'slowly' adjusts container size, unhides children - // this process repeats until children fit - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setVisible(draw_children); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - (*iit)->setVisible(draw_children); - } - - // we don't draw the open folder arrow in minimized mode - if (mHasArrow && !mCollapsedMode) - { - // update the rotation angle of open folder arrow - updateLabelRotation(); - drawOpenFolderArrow(default_params, sFgColor); - } - LLView::draw(); -} - -bool LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - //Will try to select a child node and then itself (if a child was not selected) - bool result = LLFolderViewFolder::handleMouseDown(x, y, mask); - - //This node (conversation) was selected and a child (participant) was not - if(result && getRoot()) - { - if(getRoot()->getCurSelectedItem() == this) - { - LLConversationItem* item = dynamic_cast(getViewModelItem()); - LLUUID session_id = item? item->getUUID() : LLUUID(); - - LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); - if (im_container->isConversationsPaneCollapsed() && im_container->getSelectedSession() == session_id) - { - im_container->collapseMessagesPane(!im_container->isMessagesPaneCollapsed()); - } - else - { - im_container->collapseMessagesPane(false); - } - } - selectConversationItem(); - } - - return result; -} - -bool LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - bool result = LLFolderViewFolder::handleMouseUp(x, y, mask); - - LLFloater* volume_floater = LLFloaterReg::findInstance("floater_voice_volume"); - LLFloater* chat_volume_floater = LLFloaterReg::findInstance("chat_voice"); - if (result - && getRoot() && (getRoot()->getCurSelectedItem() == this) - && !(volume_floater && volume_floater->isShown() && volume_floater->hasFocus()) - && !(chat_volume_floater && chat_volume_floater->isShown() && chat_volume_floater->hasFocus())) - { - LLConversationItem* item = dynamic_cast(getViewModelItem()); - LLUUID session_id = item? item->getUUID() : LLUUID(); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - if(session_floater && !session_floater->hasFocus()) - { - session_floater->setFocus(true); - } - } - - return result; -} - -bool LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - bool result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); - - if(result) - { - selectConversationItem(); - } - - return result; -} - -void LLConversationViewSession::selectConversationItem() -{ - if(getRoot()->getCurSelectedItem() == this) - { - LLConversationItem* item = dynamic_cast(getViewModelItem()); - LLUUID session_id = item? item->getUUID() : LLUUID(); - - LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); - im_container->flashConversationItemWidget(session_id,false); - im_container->selectConversationPair(session_id, false); - } -} - -// virtual -S32 LLConversationViewSession::arrange(S32* width, S32* height) -{ - //LLFolderViewFolder::arrange computes value for getIndentation() function below - S32 arranged = LLFolderViewFolder::arrange(width, height); - - S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); - - LLRect rect(mCollapsedMode ? getLocalRect().mLeft : h_pad, - getLocalRect().mTop, - getLocalRect().mRight, - getLocalRect().mTop - getItemHeight()); - mItemPanel->setShape(rect); - - return arranged; -} - -// virtual -void LLConversationViewSession::toggleOpen() -{ - // conversations should not be opened while in minimized mode - if (!mCollapsedMode) - { - LLFolderViewFolder::toggleOpen(); - - // do item's selection when opened - if (LLFolderViewFolder::isOpen()) - { - getParentFolder()->setSelection(this, true); - } - mContainer->reSelectConversation(); - } -} - -void LLConversationViewSession::toggleCollapsedMode(bool is_collapsed) -{ - mCollapsedMode = is_collapsed; - - // hide the layout stack which contains all item's child widgets - // except for the icon which we display in minimized mode - getChild("conversation_item_stack")->setVisible(!mCollapsedMode); - - S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); - - mItemPanel->translate(mCollapsedMode ? -h_pad : h_pad, 0); -} - -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 - LLFloater* session_floater = getSessionFloater(); - if (session_floater && session_floater->isDetachedAndNotMinimized()) - { - session_floater->setVisible(visible); - } -} - -LLFloater* LLConversationViewSession::getSessionFloater() -{ - LLFolderViewModelItem* item = mViewModelItem; - LLUUID session_uuid = dynamic_cast(item)->getUUID(); - return LLFloaterIMSessionTab::getConversation(session_uuid); -} - -LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id) -{ - // This is *not* a general tree parsing algorithm. We search only in the mItems list - // assuming there is no mFolders which makes sense for sessions (sessions don't contain - // sessions). - LLConversationViewParticipant* participant = NULL; - items_t::const_iterator iter; - for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) - { - participant = dynamic_cast(*iter); - if (participant->hasSameValue(participant_id)) - { - break; - } - } - return (iter == getItemsEnd() ? NULL : participant); -} - -void LLConversationViewSession::showVoiceIndicator(bool visible) -{ - mCallIconLayoutPanel->setVisible(visible && LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()); - requestArrange(); -} - -void LLConversationViewSession::refresh() -{ - // Refresh the session view from its model data - LLConversationItem* vmi = dynamic_cast(getViewModelItem()); - if (vmi) - { - vmi->resetRefresh(); - - if (mSessionTitle) - { - if (!highlightFriendTitle(vmi)) - { - LLStyle::Params title_style; - title_style.color = LLUIColorTable::instance().getColor("LabelTextColor"); - mSessionTitle->setText(vmi->getDisplayName(), title_style); - } - } - } - - // Update all speaking indicators - LLSpeakingIndicatorManager::updateSpeakingIndicators(); - - // we should show indicator for specified voice session only if this is current channel. EXT-5562. - if (mSpeakingIndicator) - { - mSpeakingIndicator->setIsActiveChannel(mIsInActiveVoiceChannel); - mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel); - } - - LLConversationViewParticipant* participant = NULL; - items_t::const_iterator iter; - for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) - { - participant = dynamic_cast(*iter); - if (participant) - { - participant->allowSpeakingIndicator(mIsInActiveVoiceChannel); - } - } - - requestArrange(); - if (vmi) - { - // Do the regular upstream refresh - LLFolderViewFolder::refresh(); - } -} - -void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) -{ - LLConversationItem* vmi = dynamic_cast(getViewModelItem()); - - if (vmi) - { - bool old_value = mIsInActiveVoiceChannel; - mIsInActiveVoiceChannel = vmi->getUUID() == session_id; - mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel); - if (old_value != mIsInActiveVoiceChannel) - { - refresh(); - } - } -} - -bool LLConversationViewSession::highlightFriendTitle(LLConversationItem* vmi) -{ - if(vmi->getType() == LLConversationItem::CONV_PARTICIPANT || vmi->getType() == LLConversationItem::CONV_SESSION_1_ON_1) - { - LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID()); - if (session && LLAvatarActions::isFriend(session->mOtherParticipantID)) - { - LLStyle::Params title_style; - title_style.color = LLUIColorTable::instance().getColor("ConversationFriendColor"); - mSessionTitle->setText(vmi->getDisplayName(), title_style); - return true; - } - } - return false; -} - -// -// Implementation of conversations list participant (avatar) widgets -// - -static LLDefaultChildRegistry::Register r("conversation_view_participant"); -bool LLConversationViewParticipant::sStaticInitialized = false; -S32 LLConversationViewParticipant::sChildrenWidths[LLConversationViewParticipant::ALIC_COUNT]; - -LLConversationViewParticipant::Params::Params() : -container(), -participant_id(), -avatar_icon("avatar_icon"), -info_button("info_button"), -output_monitor("output_monitor") -{} - -LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): - LLFolderViewItem(p), - mAvatarIcon(NULL), - mInfoBtn(NULL), - mSpeakingIndicator(NULL), - mUUID(p.participant_id) -{ -} - -LLConversationViewParticipant::~LLConversationViewParticipant() -{ - mActiveVoiceChannelConnection.disconnect(); -} - -void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) -{ - LLAvatarIconCtrl::Params avatar_icon_params(params.avatar_icon()); - applyXUILayout(avatar_icon_params, this); - LLAvatarIconCtrl * avatarIcon = LLUICtrlFactory::create(avatar_icon_params); - addChild(avatarIcon); - - LLButton::Params info_button_params(params.info_button()); - applyXUILayout(info_button_params, this); - LLButton * button = LLUICtrlFactory::create(info_button_params); - addChild(button); - - LLOutputMonitorCtrl::Params output_monitor_params(params.output_monitor()); - applyXUILayout(output_monitor_params, this); - LLOutputMonitorCtrl * outputMonitor = LLUICtrlFactory::create(output_monitor_params); - addChild(outputMonitor); -} - -bool LLConversationViewParticipant::postBuild() -{ - mAvatarIcon = getChild("avatar_icon"); - - mInfoBtn = getChild("info_btn"); - mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); - mInfoBtn->setVisible(false); - - mSpeakingIndicator = getChild("speaking_indicator"); - - if (!sStaticInitialized) - { - // Remember children widths including their padding from the next sibling, - // so that we can hide and show them again later. - initChildrenWidths(this); - sStaticInitialized = true; - } - - updateChildren(); - if (getViewModelItem()) - { - LLFolderViewItem::postBuild(); - refresh(); - } - return true; -} - -void LLConversationViewParticipant::draw() -{ - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - - const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); - - const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - F32 right_x = 0; - - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad; - F32 text_left = (F32)getLabelXPos(); - - LLColor4 color; - - LLLocalSpeakerMgr *speakerMgr = LLLocalSpeakerMgr::getInstance(); - - if (speakerMgr && speakerMgr->isSpeakerToBeRemoved(mUUID)) - { - color = sFgDisabledColor; - } - else - { - if (LLAvatarActions::isFriend(mUUID)) - { - color = LLUIColorTable::instance().getColor("ConversationFriendColor"); - } - else - { - color = mIsSelected ? sHighlightFgColor : sFgColor; - } - } - - LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); - if (participant_model) - { - mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); - } - - drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); - drawLabel(font, text_left, y, color, right_x); - - 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); - - //Since dimensions changed, adjust the children (info button, speaker indicator) - updateChildren(); - - return arranged; -} - -// virtual -void LLConversationViewParticipant::refresh() -{ - // Refresh the participant view from its model data - LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); - if (participant_model) - { - participant_model->resetRefresh(); - - // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat - mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); - - // Do the regular upstream refresh - LLFolderViewItem::refresh(); - } -} - -void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) -{ - // Add the item to the folder (conversation) - LLFolderViewItem::addToFolder(folder); - - // Retrieve the folder (conversation) UUID, which is also the speaker session UUID - LLFolderViewFolder *prnt = getParentFolder(); - if (prnt) - { - LLConversationItem* vmi = dynamic_cast(prnt->getViewModelItem()); - if (vmi) - { - addToSession(vmi->getUUID()); - } - LLConversationViewSession* session = dynamic_cast(prnt); - if (session) - { - allowSpeakingIndicator(session->isInActiveVoiceChannel()); - } - } -} - -void LLConversationViewParticipant::addToSession(const LLUUID& session_id) -{ - //Allows speaking icon image to be loaded based on mUUID - mAvatarIcon->setValue(mUUID); - - //Allows the speaker indicator to be activated based on the user and conversation - mSpeakingIndicator->setSpeakerId(mUUID, session_id); -} - -void LLConversationViewParticipant::onInfoBtnClick() -{ - LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); -} - -bool LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - bool result = LLFolderViewItem::handleMouseDown(x, y, mask); - - if(result && getRoot()) - { - if(getRoot()->getCurSelectedItem() == this) - { - LLConversationItem* vmi = getParentFolder() ? dynamic_cast(getParentFolder()->getViewModelItem()) : NULL; - LLUUID session_id = vmi? vmi->getUUID() : LLUUID(); - - LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - im_container->setSelectedSession(session_id); - im_container->flashConversationItemWidget(session_id,false); - im_container->selectFloater(session_floater); - im_container->collapseMessagesPane(false); - } - } - return result; -} - -void LLConversationViewParticipant::onMouseEnter(S32 x, S32 y, MASK mask) -{ - mInfoBtn->setVisible(true); - updateChildren(); - LLFolderViewItem::onMouseEnter(x, y, mask); -} - -void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mInfoBtn->setVisible(false); - updateChildren(); - LLFolderViewItem::onMouseLeave(x, y, mask); -} - -S32 LLConversationViewParticipant::getLabelXPos() -{ - return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad; -} - -// static -void LLConversationViewParticipant::initChildrenWidths(LLConversationViewParticipant* self) -{ - //speaking indicator width + padding - S32 speaking_indicator_width = self->getRect().getWidth() - self->mSpeakingIndicator->getRect().mLeft; - - //info btn width + padding - S32 info_btn_width = self->mSpeakingIndicator->getRect().mLeft - self->mInfoBtn->getRect().mLeft; - - S32 index = ALIC_COUNT; - sChildrenWidths[--index] = info_btn_width; - sChildrenWidths[--index] = speaking_indicator_width; - llassert(index == 0); -} - -void LLConversationViewParticipant::updateChildren() -{ - mLabelPaddingRight = DEFAULT_LABEL_PADDING_RIGHT; - LLView* control; - S32 ctrl_width; - LLRect controlRect; - - //Cycles through controls starting from right to left - for (S32 i = 0; i < ALIC_COUNT; ++i) - { - control = getItemChildView((EAvatarListItemChildIndex)i); - - // skip invisible views - if (!control->getVisible()) continue; - - //Get current pos/dimensions - controlRect = control->getRect(); - - ctrl_width = sChildrenWidths[i]; // including space between current & left controls - // accumulate the amount of space taken by the controls - mLabelPaddingRight += ctrl_width; - - //Reposition visible controls in case adjacent controls to the right are hidden. - controlRect.setLeftTopAndSize( - getLocalRect().getWidth() - mLabelPaddingRight, - controlRect.mTop, - controlRect.getWidth(), - controlRect.getHeight()); - - //Sets the new position - control->setShape(controlRect); - } -} - -LLView* LLConversationViewParticipant::getItemChildView(EAvatarListItemChildIndex child_view_index) -{ - LLView* child_view = NULL; - - switch (child_view_index) - { - case ALIC_SPEAKER_INDICATOR: - child_view = mSpeakingIndicator; - break; - case ALIC_INFO_BUTTON: - child_view = mInfoBtn; - break; - default: - LL_WARNS("AvatarItemReshape") << "Unexpected child view index is passed: " << child_view_index << LL_ENDL; - llassert(0); - break; - // leave child_view untouched - } - - return child_view; -} - -void LLConversationViewParticipant::allowSpeakingIndicator(bool val) -{ - mSpeakingIndicator->setIsActiveChannel(val); -} - -// EOF - +/** + * @file llconversationview.cpp + * @brief Implementation of conversations list widgets and views + * + * $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 "llconversationview.h" + +#include +#include "llagentdata.h" +#include "llavataractions.h" +#include "llconversationmodel.h" +#include "llfloaterimsession.h" +#include "llfloaterimnearbychat.h" +#include "llfloaterimsessiontab.h" +#include "llfloaterimcontainer.h" +#include "llfloaterreg.h" +#include "llgroupiconctrl.h" +#include "lluictrlfactory.h" +#include "lltoolbarview.h" + +// +// Implementation of conversations list session widgets +// +static LLDefaultChildRegistry::Register r_conversation_view_session("conversation_view_session"); + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + +class LLNearbyVoiceClientStatusObserver : public LLVoiceClientStatusObserver +{ +public: + + LLNearbyVoiceClientStatusObserver(LLConversationViewSession* conv) + : conversation(conv) + {} + + virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) + { + conversation->showVoiceIndicator(conversation + && status != STATUS_JOINING + && status != STATUS_LEFT_CHANNEL + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking()); + } + +private: + LLConversationViewSession* conversation; +}; + +LLConversationViewSession::Params::Params() : + container() +{} + +LLConversationViewSession::LLConversationViewSession(const LLConversationViewSession::Params& p): + LLFolderViewFolder(p), + mContainer(p.container), + mItemPanel(NULL), + mCallIconLayoutPanel(NULL), + mSessionTitle(NULL), + mSpeakingIndicator(NULL), + mVoiceClientObserver(NULL), + mCollapsedMode(false), + mHasArrow(true), + mIsInActiveVoiceChannel(false), + mFlashStateOn(false), + mFlashStarted(false) +{ + mFlashTimer = new LLFlashTimer(); + mAreChildrenInited = true; // inventory only +} + +LLConversationViewSession::~LLConversationViewSession() +{ + mActiveVoiceChannelConnection.disconnect(); + + if (mVoiceClientObserver) + { + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); + } + delete mVoiceClientObserver; + } + + mFlashTimer->unset(); + delete mFlashTimer; + mFlashStateOn = false; +} + +void LLConversationViewSession::destroyView() +{ + // Chat can create and parent models(listeners) to session's model before creating + // coresponding views, such participant's models normally will wait for idle cycles + // but since we are deleting session and won't be processing any more events, make + // sure unowned LLConversationItemParticipant models are removed as well. + + LLConversationItemSession* vmi = dynamic_cast(getViewModelItem()); + + // CONV_SESSION_1_ON_1 stores participants as two models that belong to views independent + // from session (nasty! These views are widgets in LLFloaterIMSessionTab, see buildConversationViewParticipant) + if (vmi && vmi->getType() != LLConversationItem::CONV_SESSION_1_ON_1) + { + // Destroy existing views + while (!mItems.empty()) + { + LLFolderViewItem *itemp = mItems.back(); + mItems.pop_back(); + + LLFolderViewModelItem* item_vmi = itemp->getViewModelItem(); + if (item_vmi) // supposed to exist + { + // unparent to remove from child list + vmi->removeChild(item_vmi); + } + itemp->destroyView(); + } + + // Not needed in scope of sessions, but just in case + while (!mFolders.empty()) + { + LLFolderViewFolder *folderp = mFolders.back(); + mFolders.pop_back(); + + LLFolderViewModelItem* folder_vmi = folderp->getViewModelItem(); + if (folder_vmi) + { + vmi->removeChild(folder_vmi); + } + folderp->destroyView(); + } + + // Now everything that is left in model(listener) is not owned by views, + // only by sessions, deparent so it won't point to soon to be dead model + vmi->clearAndDeparentModels(); + } + + LLFolderViewFolder::destroyView(); +} + +void LLConversationViewSession::setFlashState(bool flash_state) +{ + if (flash_state && !mFlashStateOn) + { + // flash chat toolbar button if scrolled out of sight (because flashing will not be visible) + if (mContainer->isScrolledOutOfSight(this)) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } + + mFlashStateOn = flash_state; + mFlashStarted = false; + mFlashTimer->stopFlashing(); +} + +void LLConversationViewSession::setHighlightState(bool hihglight_state) +{ + mFlashStateOn = hihglight_state; + mFlashStarted = true; + mFlashTimer->stopFlashing(); +} + +void LLConversationViewSession::startFlashing() +{ + // Need to start flashing only when "Conversations" is opened or brought on top + if (isInVisibleChain() + && mFlashStateOn + && !mFlashStarted + && ! LLFloaterReg::getTypedInstance("im_container")->isMinimized() ) + { + mFlashStarted = true; + mFlashTimer->startFlashing(); + } +} + +bool LLConversationViewSession::isHighlightAllowed() +{ + return mFlashStateOn || mIsSelected; +} + +bool LLConversationViewSession::isHighlightActive() +{ + return (mFlashStateOn ? (mFlashTimer->isFlashingInProgress() ? mFlashTimer->isCurrentlyHighlighted() : true) : mIsCurSelection); +} + +bool LLConversationViewSession::postBuild() +{ + LLFolderViewItem::postBuild(); + + mItemPanel = LLUICtrlFactory::getInstance()->createFromFile("panel_conversation_list_item.xml", NULL, LLPanel::child_registry_t::instance()); + addChild(mItemPanel); + + mCallIconLayoutPanel = mItemPanel->getChild("call_icon_panel"); + mSessionTitle = mItemPanel->getChild("conversation_title"); + + mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewSession::onCurrentVoiceSessionChanged, this, _1)); + mSpeakingIndicator = getChild("speaking_indicator"); + + LLConversationItem* vmi = dynamic_cast(getViewModelItem()); + if (vmi) + { + switch(vmi->getType()) + { + case LLConversationItem::CONV_PARTICIPANT: + case LLConversationItem::CONV_SESSION_1_ON_1: + { + LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID()); + if (session) + { + LLAvatarIconCtrl* icon = mItemPanel->getChild("avatar_icon"); + icon->setVisible(true); + icon->setValue(session->mOtherParticipantID); + mSpeakingIndicator->setSpeakerId(session->mOtherParticipantID, session->mSessionID, true); + mHasArrow = false; + } + break; + } + case LLConversationItem::CONV_SESSION_AD_HOC: + { + LLGroupIconCtrl* icon = mItemPanel->getChild("group_icon"); + icon->setVisible(true); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); + break; + } + case LLConversationItem::CONV_SESSION_GROUP: + { + LLGroupIconCtrl* icon = mItemPanel->getChild("group_icon"); + icon->setVisible(true); + icon->setValue(vmi->getUUID()); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); + break; + } + case LLConversationItem::CONV_SESSION_NEARBY: + { + LLIconCtrl* icon = mItemPanel->getChild("nearby_chat_icon"); + icon->setVisible(true); + mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); + mIsInActiveVoiceChannel = true; + if(LLVoiceClient::instanceExists()) + { + if (mVoiceClientObserver) + { + LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); + delete mVoiceClientObserver; + } + mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); + LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver); + } + break; + } + default: + break; + } + + refresh(); // requires vmi + } + + return true; +} + +void LLConversationViewSession::draw() +{ + getViewModelItem()->update(); + + const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams(); + const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); + + // Indicate that flash can start (moot operation if already started, done or not flashing) + startFlashing(); + + // draw highlight for selected items + drawHighlight(show_context, true, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); + + // Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap. + bool draw_children = getRoot() == static_cast(this) || isOpen(); + + // Todo/fix this: arrange hides children 'out of bonds', session 'slowly' adjusts container size, unhides children + // this process repeats until children fit + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setVisible(draw_children); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + (*iit)->setVisible(draw_children); + } + + // we don't draw the open folder arrow in minimized mode + if (mHasArrow && !mCollapsedMode) + { + // update the rotation angle of open folder arrow + updateLabelRotation(); + drawOpenFolderArrow(default_params, sFgColor); + } + LLView::draw(); +} + +bool LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + //Will try to select a child node and then itself (if a child was not selected) + bool result = LLFolderViewFolder::handleMouseDown(x, y, mask); + + //This node (conversation) was selected and a child (participant) was not + if(result && getRoot()) + { + if(getRoot()->getCurSelectedItem() == this) + { + LLConversationItem* item = dynamic_cast(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); + if (im_container->isConversationsPaneCollapsed() && im_container->getSelectedSession() == session_id) + { + im_container->collapseMessagesPane(!im_container->isMessagesPaneCollapsed()); + } + else + { + im_container->collapseMessagesPane(false); + } + } + selectConversationItem(); + } + + return result; +} + +bool LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + bool result = LLFolderViewFolder::handleMouseUp(x, y, mask); + + LLFloater* volume_floater = LLFloaterReg::findInstance("floater_voice_volume"); + LLFloater* chat_volume_floater = LLFloaterReg::findInstance("chat_voice"); + if (result + && getRoot() && (getRoot()->getCurSelectedItem() == this) + && !(volume_floater && volume_floater->isShown() && volume_floater->hasFocus()) + && !(chat_volume_floater && chat_volume_floater->isShown() && chat_volume_floater->hasFocus())) + { + LLConversationItem* item = dynamic_cast(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + if(session_floater && !session_floater->hasFocus()) + { + session_floater->setFocus(true); + } + } + + return result; +} + +bool LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + bool result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); + + if(result) + { + selectConversationItem(); + } + + return result; +} + +void LLConversationViewSession::selectConversationItem() +{ + if(getRoot()->getCurSelectedItem() == this) + { + LLConversationItem* item = dynamic_cast(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); + im_container->flashConversationItemWidget(session_id,false); + im_container->selectConversationPair(session_id, false); + } +} + +// virtual +S32 LLConversationViewSession::arrange(S32* width, S32* height) +{ + //LLFolderViewFolder::arrange computes value for getIndentation() function below + S32 arranged = LLFolderViewFolder::arrange(width, height); + + S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); + + LLRect rect(mCollapsedMode ? getLocalRect().mLeft : h_pad, + getLocalRect().mTop, + getLocalRect().mRight, + getLocalRect().mTop - getItemHeight()); + mItemPanel->setShape(rect); + + return arranged; +} + +// virtual +void LLConversationViewSession::toggleOpen() +{ + // conversations should not be opened while in minimized mode + if (!mCollapsedMode) + { + LLFolderViewFolder::toggleOpen(); + + // do item's selection when opened + if (LLFolderViewFolder::isOpen()) + { + getParentFolder()->setSelection(this, true); + } + mContainer->reSelectConversation(); + } +} + +void LLConversationViewSession::toggleCollapsedMode(bool is_collapsed) +{ + mCollapsedMode = is_collapsed; + + // hide the layout stack which contains all item's child widgets + // except for the icon which we display in minimized mode + getChild("conversation_item_stack")->setVisible(!mCollapsedMode); + + S32 h_pad = mHasArrow ? getIndentation() + mArrowSize : getIndentation(); + + mItemPanel->translate(mCollapsedMode ? -h_pad : h_pad, 0); +} + +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 + LLFloater* session_floater = getSessionFloater(); + if (session_floater && session_floater->isDetachedAndNotMinimized()) + { + session_floater->setVisible(visible); + } +} + +LLFloater* LLConversationViewSession::getSessionFloater() +{ + LLFolderViewModelItem* item = mViewModelItem; + LLUUID session_uuid = dynamic_cast(item)->getUUID(); + return LLFloaterIMSessionTab::getConversation(session_uuid); +} + +LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id) +{ + // This is *not* a general tree parsing algorithm. We search only in the mItems list + // assuming there is no mFolders which makes sense for sessions (sessions don't contain + // sessions). + LLConversationViewParticipant* participant = NULL; + items_t::const_iterator iter; + for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) + { + participant = dynamic_cast(*iter); + if (participant->hasSameValue(participant_id)) + { + break; + } + } + return (iter == getItemsEnd() ? NULL : participant); +} + +void LLConversationViewSession::showVoiceIndicator(bool visible) +{ + mCallIconLayoutPanel->setVisible(visible && LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()); + requestArrange(); +} + +void LLConversationViewSession::refresh() +{ + // Refresh the session view from its model data + LLConversationItem* vmi = dynamic_cast(getViewModelItem()); + if (vmi) + { + vmi->resetRefresh(); + + if (mSessionTitle) + { + if (!highlightFriendTitle(vmi)) + { + LLStyle::Params title_style; + title_style.color = LLUIColorTable::instance().getColor("LabelTextColor"); + mSessionTitle->setText(vmi->getDisplayName(), title_style); + } + } + } + + // Update all speaking indicators + LLSpeakingIndicatorManager::updateSpeakingIndicators(); + + // we should show indicator for specified voice session only if this is current channel. EXT-5562. + if (mSpeakingIndicator) + { + mSpeakingIndicator->setIsActiveChannel(mIsInActiveVoiceChannel); + mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel); + } + + LLConversationViewParticipant* participant = NULL; + items_t::const_iterator iter; + for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) + { + participant = dynamic_cast(*iter); + if (participant) + { + participant->allowSpeakingIndicator(mIsInActiveVoiceChannel); + } + } + + requestArrange(); + if (vmi) + { + // Do the regular upstream refresh + LLFolderViewFolder::refresh(); + } +} + +void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) +{ + LLConversationItem* vmi = dynamic_cast(getViewModelItem()); + + if (vmi) + { + bool old_value = mIsInActiveVoiceChannel; + mIsInActiveVoiceChannel = vmi->getUUID() == session_id; + mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel); + if (old_value != mIsInActiveVoiceChannel) + { + refresh(); + } + } +} + +bool LLConversationViewSession::highlightFriendTitle(LLConversationItem* vmi) +{ + if(vmi->getType() == LLConversationItem::CONV_PARTICIPANT || vmi->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID()); + if (session && LLAvatarActions::isFriend(session->mOtherParticipantID)) + { + LLStyle::Params title_style; + title_style.color = LLUIColorTable::instance().getColor("ConversationFriendColor"); + mSessionTitle->setText(vmi->getDisplayName(), title_style); + return true; + } + } + return false; +} + +// +// Implementation of conversations list participant (avatar) widgets +// + +static LLDefaultChildRegistry::Register r("conversation_view_participant"); +bool LLConversationViewParticipant::sStaticInitialized = false; +S32 LLConversationViewParticipant::sChildrenWidths[LLConversationViewParticipant::ALIC_COUNT]; + +LLConversationViewParticipant::Params::Params() : +container(), +participant_id(), +avatar_icon("avatar_icon"), +info_button("info_button"), +output_monitor("output_monitor") +{} + +LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): + LLFolderViewItem(p), + mAvatarIcon(NULL), + mInfoBtn(NULL), + mSpeakingIndicator(NULL), + mUUID(p.participant_id) +{ +} + +LLConversationViewParticipant::~LLConversationViewParticipant() +{ + mActiveVoiceChannelConnection.disconnect(); +} + +void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) +{ + LLAvatarIconCtrl::Params avatar_icon_params(params.avatar_icon()); + applyXUILayout(avatar_icon_params, this); + LLAvatarIconCtrl * avatarIcon = LLUICtrlFactory::create(avatar_icon_params); + addChild(avatarIcon); + + LLButton::Params info_button_params(params.info_button()); + applyXUILayout(info_button_params, this); + LLButton * button = LLUICtrlFactory::create(info_button_params); + addChild(button); + + LLOutputMonitorCtrl::Params output_monitor_params(params.output_monitor()); + applyXUILayout(output_monitor_params, this); + LLOutputMonitorCtrl * outputMonitor = LLUICtrlFactory::create(output_monitor_params); + addChild(outputMonitor); +} + +bool LLConversationViewParticipant::postBuild() +{ + mAvatarIcon = getChild("avatar_icon"); + + mInfoBtn = getChild("info_btn"); + mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); + mInfoBtn->setVisible(false); + + mSpeakingIndicator = getChild("speaking_indicator"); + + if (!sStaticInitialized) + { + // Remember children widths including their padding from the next sibling, + // so that we can hide and show them again later. + initChildrenWidths(this); + sStaticInitialized = true; + } + + updateChildren(); + if (getViewModelItem()) + { + LLFolderViewItem::postBuild(); + refresh(); + } + return true; +} + +void LLConversationViewParticipant::draw() +{ + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); + + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + F32 right_x = 0; + + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad; + F32 text_left = (F32)getLabelXPos(); + + LLColor4 color; + + LLLocalSpeakerMgr *speakerMgr = LLLocalSpeakerMgr::getInstance(); + + if (speakerMgr && speakerMgr->isSpeakerToBeRemoved(mUUID)) + { + color = sFgDisabledColor; + } + else + { + if (LLAvatarActions::isFriend(mUUID)) + { + color = LLUIColorTable::instance().getColor("ConversationFriendColor"); + } + else + { + color = mIsSelected ? sHighlightFgColor : sFgColor; + } + } + + LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); + if (participant_model) + { + mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); + } + + drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); + drawLabel(font, text_left, y, color, right_x); + + 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); + + //Since dimensions changed, adjust the children (info button, speaker indicator) + updateChildren(); + + return arranged; +} + +// virtual +void LLConversationViewParticipant::refresh() +{ + // Refresh the participant view from its model data + LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); + if (participant_model) + { + participant_model->resetRefresh(); + + // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat + mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); + + // Do the regular upstream refresh + LLFolderViewItem::refresh(); + } +} + +void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) +{ + // Add the item to the folder (conversation) + LLFolderViewItem::addToFolder(folder); + + // Retrieve the folder (conversation) UUID, which is also the speaker session UUID + LLFolderViewFolder *prnt = getParentFolder(); + if (prnt) + { + LLConversationItem* vmi = dynamic_cast(prnt->getViewModelItem()); + if (vmi) + { + addToSession(vmi->getUUID()); + } + LLConversationViewSession* session = dynamic_cast(prnt); + if (session) + { + allowSpeakingIndicator(session->isInActiveVoiceChannel()); + } + } +} + +void LLConversationViewParticipant::addToSession(const LLUUID& session_id) +{ + //Allows speaking icon image to be loaded based on mUUID + mAvatarIcon->setValue(mUUID); + + //Allows the speaker indicator to be activated based on the user and conversation + mSpeakingIndicator->setSpeakerId(mUUID, session_id); +} + +void LLConversationViewParticipant::onInfoBtnClick() +{ + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); +} + +bool LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + bool result = LLFolderViewItem::handleMouseDown(x, y, mask); + + if(result && getRoot()) + { + if(getRoot()->getCurSelectedItem() == this) + { + LLConversationItem* vmi = getParentFolder() ? dynamic_cast(getParentFolder()->getViewModelItem()) : NULL; + LLUUID session_id = vmi? vmi->getUUID() : LLUUID(); + + LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + im_container->setSelectedSession(session_id); + im_container->flashConversationItemWidget(session_id,false); + im_container->selectFloater(session_floater); + im_container->collapseMessagesPane(false); + } + } + return result; +} + +void LLConversationViewParticipant::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mInfoBtn->setVisible(true); + updateChildren(); + LLFolderViewItem::onMouseEnter(x, y, mask); +} + +void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mInfoBtn->setVisible(false); + updateChildren(); + LLFolderViewItem::onMouseLeave(x, y, mask); +} + +S32 LLConversationViewParticipant::getLabelXPos() +{ + return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad; +} + +// static +void LLConversationViewParticipant::initChildrenWidths(LLConversationViewParticipant* self) +{ + //speaking indicator width + padding + S32 speaking_indicator_width = self->getRect().getWidth() - self->mSpeakingIndicator->getRect().mLeft; + + //info btn width + padding + S32 info_btn_width = self->mSpeakingIndicator->getRect().mLeft - self->mInfoBtn->getRect().mLeft; + + S32 index = ALIC_COUNT; + sChildrenWidths[--index] = info_btn_width; + sChildrenWidths[--index] = speaking_indicator_width; + llassert(index == 0); +} + +void LLConversationViewParticipant::updateChildren() +{ + mLabelPaddingRight = DEFAULT_LABEL_PADDING_RIGHT; + LLView* control; + S32 ctrl_width; + LLRect controlRect; + + //Cycles through controls starting from right to left + for (S32 i = 0; i < ALIC_COUNT; ++i) + { + control = getItemChildView((EAvatarListItemChildIndex)i); + + // skip invisible views + if (!control->getVisible()) continue; + + //Get current pos/dimensions + controlRect = control->getRect(); + + ctrl_width = sChildrenWidths[i]; // including space between current & left controls + // accumulate the amount of space taken by the controls + mLabelPaddingRight += ctrl_width; + + //Reposition visible controls in case adjacent controls to the right are hidden. + controlRect.setLeftTopAndSize( + getLocalRect().getWidth() - mLabelPaddingRight, + controlRect.mTop, + controlRect.getWidth(), + controlRect.getHeight()); + + //Sets the new position + control->setShape(controlRect); + } +} + +LLView* LLConversationViewParticipant::getItemChildView(EAvatarListItemChildIndex child_view_index) +{ + LLView* child_view = NULL; + + switch (child_view_index) + { + case ALIC_SPEAKER_INDICATOR: + child_view = mSpeakingIndicator; + break; + case ALIC_INFO_BUTTON: + child_view = mInfoBtn; + break; + default: + LL_WARNS("AvatarItemReshape") << "Unexpected child view index is passed: " << child_view_index << LL_ENDL; + llassert(0); + break; + // leave child_view untouched + } + + return child_view; +} + +void LLConversationViewParticipant::allowSpeakingIndicator(bool val) +{ + mSpeakingIndicator->setIsActiveChannel(val); +} + +// EOF + -- cgit v1.2.3 From e086437f12db31cb2dcc2e8fdf12794cc802cc0d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 13 Aug 2024 08:55:23 +0300 Subject: viewer-private#262 webrtc crashes on shutdown removeObserver failed to remove an im session floater --- indra/newview/llconversationview.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'indra/newview/llconversationview.cpp') diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 117dab8d58..03eb9f0652 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -98,10 +98,7 @@ LLConversationViewSession::~LLConversationViewSession() if (mVoiceClientObserver) { - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); - } + LLVoiceClient::removeObserver(mVoiceClientObserver); delete mVoiceClientObserver; } @@ -259,16 +256,15 @@ BOOL LLConversationViewSession::postBuild() icon->setVisible(true); mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); mIsInActiveVoiceChannel = true; - if(LLVoiceClient::instanceExists()) + + if (mVoiceClientObserver) { - if (mVoiceClientObserver) - { - LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); - delete mVoiceClientObserver; - } - mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); - LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver); + LLVoiceClient::removeObserver(mVoiceClientObserver); + delete mVoiceClientObserver; } + mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); + LLVoiceClient::addObserver(mVoiceClientObserver); + break; } default: -- cgit v1.2.3