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