diff options
Diffstat (limited to 'indra/newview/llimconversation.cpp')
-rw-r--r-- | indra/newview/llimconversation.cpp | 217 |
1 files changed, 177 insertions, 40 deletions
diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 51e4fbfe19..a321b3545a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -29,6 +29,8 @@ #include "llimconversation.h" +#include "llagent.h" +#include "llavataractions.h" #include "llchatentry.h" #include "llchathistory.h" #include "llchiclet.h" @@ -49,7 +51,7 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) , mTearOffBtn(NULL) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) - , mParticipantList(NULL) + , mConversationsRoot(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -74,12 +76,6 @@ LLIMConversation::LLIMConversation(const LLSD& session_id) LLIMConversation::~LLIMConversation() { - if (mParticipantList) - { - delete mParticipantList; - mParticipantList = NULL; - } - delete mRefreshTimer; } @@ -178,7 +174,8 @@ void LLIMConversation::addToHost(const LLUUID& session_id) conversp->setHost(floater_container); conversp->setHost(NULL); } - + // Added floaters share some state (like sort order) with their host + conversp->setSortOrder(floater_container->getSortOrder()); } } } @@ -193,11 +190,39 @@ BOOL LLIMConversation::postBuild() mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); - mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); - mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + + // Create a root view folder for all participants + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + + // Add a scroller for the folder (participant) view + LLRect scroller_view_rect = mParticipantListPanel->getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); + scroller_params.rect(scroller_view_rect); + LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + scroller->setFollowsAll(); + + // Insert that scroller into the panel widgets hierarchy and folder view + mParticipantListPanel->addChild(scroller); + scroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(scroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + + mChatHistory = getChild<LLChatHistory>("chat_history"); mInputEditor = getChild<LLChatEntry>("chat_editor"); @@ -210,9 +235,7 @@ BOOL LLIMConversation::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - buildParticipantList(); - - updateHeaderAndToolbar(); + buildConversationViewParticipant(); mSaveRect = isTornOff(); initRectControl(); @@ -226,26 +249,32 @@ BOOL LLIMConversation::postBuild() result = LLDockableFloater::postBuild(); } + refreshConversation(); + return result; } -void LLIMConversation::draw() +LLParticipantList* LLIMConversation::getParticipantList() { - LLTransientDockableFloater::draw(); + return dynamic_cast<LLParticipantList*>(LLIMFloaterContainer::getInstance()->getSessionModel(mSessionID)); +} +void LLIMConversation::draw() +{ if (mRefreshTimer->hasExpired()) { - if (mParticipantList) + if (getParticipantList()) { - mParticipantList->update(); + getParticipantList()->update(); } - refresh(); - updateHeaderAndToolbar(); + refreshConversation(); // Restart the refresh timer mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); } + + LLTransientDockableFloater::draw(); } void LLIMConversation::enableDisableCallBtn() @@ -332,41 +361,144 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) } -void LLIMConversation::buildParticipantList() +void LLIMConversation::buildConversationViewParticipant() { - if (mIsNearbyChat) + // Clear the widget list since we are rebuilding afresh from the model + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + while (widget_it != mConversationsWidgets.end()) { - LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); + removeConversationViewParticipant(widget_it->first); + // Iterators are invalidated by erase so we need to pick begin again + widget_it = mConversationsWidgets.begin(); + } + + // Get the model list + LLParticipantList* item = getParticipantList(); + if (!item) + { + // Nothing to do if the model list is empty + return; + } + + // Create the participants widgets now + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); + addConversationViewParticipant(participant_model); + current_participant_model++; + } +} + +void LLIMConversation::addConversationViewParticipant(LLConversationItem* participant_model) +{ + // Check if the model already has an associated view + LLUUID uuid = participant_model->getUUID(); + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + + // If not already present, create the participant view and attach it to the root, otherwise, just refresh it + if (widget) + { + updateConversationViewParticipant(uuid); // overkill? } else { - LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - // for group and ad-hoc chat we need to include agent into list - if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) - { - delete mParticipantList; // remove the old list and create a new one if the session id has changed - mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); - } + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + mConversationsWidgets[uuid] = participant_view; + participant_view->addToFolder(mConversationsRoot); + participant_view->setVisible(TRUE); + refreshConversation(); } - updateHeaderAndToolbar(); } -void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +void LLIMConversation::removeConversationViewParticipant(const LLUUID& participant_id) { - // TODO: Check this code when sort order menu will be added. (EM) - if (!mParticipantList) + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); + if (widget) { - return; + mConversationsRoot->extractItem(widget); + delete widget; + mConversationsWidgets.erase(participant_id); + refreshConversation(); } +} - std::string chosen_item = userdata.asString(); +void LLIMConversation::updateConversationViewParticipant(const LLUUID& participant_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); + if (widget) + { + widget->refresh(); + } + refreshConversation(); +} - if (chosen_item == "sort_name") +void LLIMConversation::refreshConversation() +{ + // Note: We collect participants names to change the session name only in the case of ad-hoc conversations + bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false); + uuid_vec_t participants_uuids; // uuids vector for building the added participants name string + // For P2P chat, we still need to update the session name who may have changed (switch display name for instance) + if (mIsP2PChat && mSession) { - mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); + participants_uuids.push_back(mSession->mOtherParticipantID); } + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + while (widget_it != mConversationsWidgets.end()) + { + // Add the participant to the list except if it's the agent itself (redundant) + if (is_ad_hoc && (widget_it->first != gAgentID)) + { + participants_uuids.push_back(widget_it->first); + } + widget_it->second->refresh(); + widget_it->second->setVisible(TRUE); + ++widget_it; + } + if (is_ad_hoc || mIsP2PChat) + { + // Build the session name and update it + std::string session_name; + if (participants_uuids.size() != 0) + { + LLAvatarActions::buildResidentsString(participants_uuids, session_name); + } + else + { + session_name = LLIMModel::instance().getName(mSessionID); + } + updateSessionName(session_name); + } + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + mConversationsRoot->update(); + updateHeaderAndToolbar(); + refresh(); +} + +// Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! +LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item) +{ + LLRect panel_rect = mParticipantListPanel->getRect(); + + LLConversationViewParticipant::Params params; + params.name = item->getDisplayName(); + params.root = mConversationsRoot; + params.listener = item; + params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); // *TODO: use conversation_view_participant.xml itemHeight value in lieu of 24 + params.tool_tip = params.name; + params.participant_id = item->getUUID(); + + return LLUICtrlFactory::create<LLConversationViewParticipant>(params); +} + +void LLIMConversation::setSortOrder(const LLConversationSort& order) +{ + mConversationViewModel.setSorter(order); + mConversationsRoot->arrangeAll(); + refreshConversation(); } void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) @@ -425,6 +557,11 @@ void LLIMConversation::hideOrShowTitle() floater_contents->setShape(contents_rect); } +void LLIMConversation::updateSessionName(const std::string& name) +{ + mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name); +} + void LLIMConversation::hideAllStandardButtons() { for (S32 i = 0; i < BUTTON_COUNT; i++) @@ -582,7 +719,7 @@ void LLIMConversation::onTearOffClicked() mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); - updateHeaderAndToolbar(); + refreshConversation(); } // static @@ -599,7 +736,7 @@ bool LLIMConversation::checkIfTornOff() if (isTorn != isTornOff()) { setTornOff(isTorn); - updateHeaderAndToolbar(); + refreshConversation(); } return isTorn; |