From 249b44d01ced4ba5bb8b8b9147d7836a7d492d5b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 16 Nov 2012 21:01:57 -0800 Subject: CHUI-479 : Fixed : Rebuild the root on the LLFloaterIMSession when modifying the session ID --- indra/newview/llfloaterimcontainer.cpp | 42 ++++++++----------- indra/newview/llfloaterimsessiontab.cpp | 72 +++++++++++++++++---------------- indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 55 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index af090338d7..bd692aa850 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -117,26 +117,20 @@ void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - llinfos << "Merov debug : sessionIDUpdated, old_session_id = " << old_session_id << ", new_session_id = " << new_session_id << llendl; - // Retrieve the session LLFloaterIMSessionTab - // just close it: that should erase the mSession, close the tab and remove the list item - // *TODO : take the mSessions element (pointing to the tab) out of the list - //bool change_focus = removeConversationListItem(old_session_id); - // *TODO : detach the old tab from the host - // *TODO : delete the tab (that's one thing that's reentrant) - LLFloater* floaterp = get_ptr_in_map(mSessions, old_session_id); - if (floaterp) - { - llinfos << "Merov debug : closeFloater, start" << llendl; - floaterp->closeFloater(); - llinfos << "Merov debug : closeFloater, end" << llendl; - } - bool change_focus = false; - llinfos << "Merov debug : addConversationListItem" << llendl; + // The general strategy when a session id is modified is to delete all related objects and create them anew. + + // Note however that the LLFloaterIMSession has its session id updated through a call to sessionInitReplyReceived() + // and do not need to be deleted and recreated (trying this creates loads of problems). We do need however to suppress + // its related mSessions record as it's indexed with the wrong id. + // Grabbing the updated LLFloaterIMSession and readding it in mSessions will eventually be done by addConversationListItem(). + mSessions.erase(old_session_id); + + // Delete the model and participants related to the old session + bool change_focus = removeConversationListItem(old_session_id); + + // Create a new conversation with the new id addConversationListItem(new_session_id, change_focus); - llinfos << "Merov debug : addToHost" << llendl; LLFloaterIMSessionTab::addToHost(new_session_id); - llinfos << "Merov debug : end sessionIDUpdated" << llendl; } void LLFloaterIMContainer::sessionRemoved(const LLUUID& session_id) @@ -483,14 +477,14 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) else if (type == "update_session") { session_view->refresh(); - if (conversation_floater) - { - conversation_floater->refreshConversation(); - } } mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); + if (conversation_floater) + { + conversation_floater->refreshConversation(); + } return false; } @@ -1253,10 +1247,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& return item_it->second; } - // Remove the conversation item that might exist already: it'll be recreated anew further down anyway - // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(uuid,false); - // Create a conversation session model LLConversationItemSession* item = NULL; LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6fbc713590..22131eac49 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -52,6 +52,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) , mConversationsRoot(NULL) + , mScroller(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -68,10 +69,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); - - // Zero expiry time is set only once to allow initial update. - mRefreshTimer->setTimerExpirySec(0); - mRefreshTimer->start(); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -195,33 +192,16 @@ BOOL LLFloaterIMSessionTab::postBuild() mParticipantListPanel = getChild("speakers_list_panel"); - // Create a root view folder for all participants - LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); - 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(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()); scroller_params.rect(scroller_view_rect); - LLScrollContainer* scroller = LLUICtrlFactory::create(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); + mScroller = LLUICtrlFactory::create(scroller_params); + mScroller->setFollowsAll(); + // Insert that scroller into the panel widgets hierarchy + mParticipantListPanel->addChild(mScroller); mChatHistory = getChild("chat_history"); @@ -235,8 +215,6 @@ BOOL LLFloaterIMSessionTab::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - buildConversationViewParticipant(); - mSaveRect = isTornOff(); initRectControl(); @@ -249,8 +227,14 @@ BOOL LLFloaterIMSessionTab::postBuild() result = LLDockableFloater::postBuild(); } + // Now ready to build the conversation and participants list + buildConversationViewParticipant(); refreshConversation(); - + + // Zero expiry time is set only once to allow initial update. + mRefreshTimer->setTimerExpirySec(0); + mRefreshTimer->start(); + return result; } @@ -276,9 +260,8 @@ void LLFloaterIMSessionTab::draw() { buildConversationViewParticipant(); } + refreshConversation(); } - - refreshConversation(); // Restart the refresh timer mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); @@ -390,7 +373,31 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() // Nothing to do if the model list is inexistent return; } - + + // Create or recreate the root folder: this is a dummy folder (not shown) but required by the LLFolderView architecture + // We need to redo this when rebuilding as the session id (mSessionID) *may* have changed + if (mConversationsRoot) + { + // Remove the old root if any + mScroller->removeChild(mConversationsRoot); + } + // Create the root using an ad-hoc base item + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); + 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(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + // Attach that root to the scroller + mScroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(mScroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + // 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(); @@ -420,7 +427,6 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p participant_view->addToFolder(mConversationsRoot); participant_view->addToSession(mSessionID); participant_view->setVisible(TRUE); - refreshConversation(); } } @@ -432,7 +438,6 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part mConversationsRoot->extractItem(widget); delete widget; mConversationsWidgets.erase(participant_id); - refreshConversation(); } } @@ -443,7 +448,6 @@ void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& part { widget->refresh(); } - refreshConversation(); } void LLFloaterIMSessionTab::refreshConversation() diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 8f5a8c2c1b..b765d121de 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -146,6 +146,7 @@ protected: conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; + LLScrollContainer* mScroller; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; -- cgit v1.2.3