From 249b44d01ced4ba5bb8b8b9147d7836a7d492d5b Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
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<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);
+	mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
+	mScroller->setFollowsAll();
 	
+	// Insert that scroller into the panel widgets hierarchy
+	mParticipantListPanel->addChild(mScroller);	
 	
 	mChatHistory = getChild<LLChatHistory>("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<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);
+	// 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