From 7f51bd7897a3ced0edc74a32b9148febd7866721 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Sat, 23 Feb 2013 11:22:09 -0800
Subject: CHUI-568 : Fixed! Implemented Ctrl-H for Nearby Chat, taking into
 account the existence of other conversations and docked/torn off state

---
 indra/llui/llfloater.cpp                |  6 ---
 indra/llui/llfloaterreg.cpp             | 65 +++++++++++++++++++--------------
 indra/newview/llfloaterimcontainer.cpp  | 24 ++++++++++++
 indra/newview/llfloaterimcontainer.h    |  2 +
 indra/newview/llfloaterimnearbychat.cpp | 20 +++++-----
 indra/newview/llfloaterimnearbychat.h   |  1 -
 6 files changed, 72 insertions(+), 46 deletions(-)

diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index bf424883b3..27dd7f5b32 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -818,12 +818,10 @@ void LLFloater::closeHostedFloater()
 	// When toggling *visibility*, close the host instead of the floater when hosted
 	if (getHost())
 	{
-		llinfos << "Merov debug : closeHostedFloater : host " << llendl;
 		getHost()->closeFloater();
 	}
 	else
 	{
-		llinfos << "Merov debug : closeHostedFloater : floater " << llendl;
 		closeFloater();
 	}
 }
@@ -1628,13 +1626,11 @@ void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
 	LLMultiFloater* hostp = getHost();
 	if (hostp)
 	{
-		llinfos << "Merov debug : setVisibleAndFrontmost : hostp->setFrontmost " << llendl;
 		hostp->setVisible(TRUE);
 		hostp->setFrontmost(take_focus);
 	}
 	else
 	{
-		llinfos << "Merov debug : setVisibleAndFrontmost : setFrontmost " << llendl;
 		setVisible(TRUE);
 		setFrontmost(take_focus);
 	}
@@ -1645,14 +1641,12 @@ void LLFloater::setFrontmost(BOOL take_focus)
 	LLMultiFloater* hostp = getHost();
 	if (hostp)
 	{
-		llinfos << "Merov debug : setFrontmost : hostp->showFloater " << llendl;
 		// this will bring the host floater to the front and select
 		// the appropriate panel
 		hostp->showFloater(this);
 	}
 	else
 	{
-		llinfos << "Merov debug : setFrontmost : bringToFront " << llendl;
 		// there are more than one floater view
 		// so we need to query our parent directly
 		((LLFloaterView*)getParent())->bringToFront(this, take_focus);
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index c0be086671..c20d863612 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -265,29 +265,22 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
 	if (instance)
 	{
 		instance->closeHostedFloater();
-		return true;
-	}
-	else
-	{
-		return false;
 	}
+	return (instance != NULL);
 }
 
 //static
 // returns true if the instance is visible when completed
 bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
 {
-	llinfos << "Merov debug : toggleInstance, name = " << name << ", key = " << key.asString() << llendl;
 	LLFloater* instance = findInstance(name, key); 
 	if (LLFloater::isShown(instance))
 	{
-		llinfos << "Merov debug : call closeHostedFloater " << llendl;
 		instance->closeHostedFloater();
 		return false;
 	}
 	else
 	{
-		llinfos << "Merov debug : call show instance " << llendl;
 		return showInstance(name, key, TRUE) ? true : false;
 	}
 }
@@ -476,8 +469,6 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
 	//       * Also, if it is not on top, bring it forward when focus is given.
 	// * Else the target floater is open, close it.
 	// 
-	llinfos << "Merov debug : toggleInstanceOrBringToFront, name = " << sdname.asString() << ", key = " << key.asString() << llendl;
-
 	std::string name = sdname.asString();
 	LLFloater* instance = getInstance(name, key); 
 	
@@ -489,29 +480,47 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
 	}
 	
 	// If hosted, we need to take that into account
-	//LLFloater* host = instance->getHost();
+	LLFloater* host = instance->getHost();
 	
-	if (instance->isMinimized())
-	{
-		llinfos << "Merov debug : unminimize, make visible and set to front " << llendl;
-		instance->setMinimized(FALSE);
-		instance->setVisibleAndFrontmost();
-	}
-	else if (!instance->isShown())
-	{
-		llinfos << "Merov debug : open, make visible and set to front " << llendl;
-		instance->openFloater(key);
-		instance->setVisibleAndFrontmost();
-	}
-	else if (!instance->isFrontmost())
+	if (host)
 	{
-		llinfos << "Merov debug : make visible and set to front " << llendl;
-		instance->setVisibleAndFrontmost();
+		if (host->isMinimized() || !host->isShown() || !host->isFrontmost())
+		{
+			host->setMinimized(FALSE);
+			instance->openFloater(key);
+			instance->setVisibleAndFrontmost();
+		}
+		else if (!instance->getVisible())
+		{
+			instance->openFloater(key);
+			instance->setVisibleAndFrontmost();
+			instance->setFocus(TRUE);
+		}
+		else
+		{
+			instance->closeHostedFloater();
+		}
 	}
 	else
 	{
-		llinfos << "Merov debug : closeHostedFloater " << llendl;
-		instance->closeHostedFloater();
+		if (instance->isMinimized())
+		{
+			instance->setMinimized(FALSE);
+			instance->setVisibleAndFrontmost();
+		}
+		else if (!instance->isShown())
+		{
+			instance->openFloater(key);
+			instance->setVisibleAndFrontmost();
+		}
+		else if (!instance->isFrontmost())
+		{
+			instance->setVisibleAndFrontmost();
+		}
+		else
+		{
+			instance->closeHostedFloater();
+		}
 	}
 }
 
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index c8088588da..73fcfa244e 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -1337,6 +1337,30 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id)
     selectConversationPair(session_id, true);
 }
 
+// Select the conversation *after* (or before if none after) the passed uuid conversation
+// Used to change the selection on key hits
+void LLFloaterIMContainer::selectNextConversation(const LLUUID& uuid)
+{
+	LLFolderViewItem* new_selection = NULL;
+	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
+	if (widget)
+	{
+		new_selection = mConversationsRoot->getNextFromChild(widget, FALSE);
+		if (!new_selection)
+		{
+			new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE);
+		}
+	}
+	if (new_selection)
+	{
+		LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem());
+		if (vmi)
+		{
+			selectConversationPair(vmi->getUUID(), true);
+		}
+	}
+}
+
 // Synchronous select the conversation item and the conversation floater
 BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget)
 {
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 569fa9faab..33d63a391c 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -69,6 +69,7 @@ public:
 	void returnFloaterToHost();
     void showConversation(const LLUUID& session_id);
     void selectConversation(const LLUUID& session_id);
+	void selectNextConversation(const LLUUID& session_id);
     BOOL selectConversationPair(const LLUUID& session_id, bool select_widget);
     void clearAllFlashStates();
 
@@ -186,6 +187,7 @@ public:
 	static bool isConversationLoggingAllowed();
 	void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes);
 	boost::signals2::connection mMicroChangedSignal;
+	S32 getConversationListItemSize() { return mConversationsWidgets.size(); }
 
 private:
 	LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 80051eb7f1..a3b81e037a 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -135,24 +135,22 @@ BOOL LLFloaterIMNearbyChat::postBuild()
 	return result;
 }
 
-// virtual
-void LLFloaterIMNearbyChat::closeFloater(bool app_quitting)
-{
-	llinfos << "Merov debug : LLFloaterIMNearbyChat::closeFloater! " << llendl;
-	LLFloater::closeFloater(app_quitting);
-}
-
 // virtual
 void LLFloaterIMNearbyChat::closeHostedFloater()
 {
-	if (getHost())
+	// Should check how many conversations are ongoing. Close all if 1 only (the Nearby Chat), select next one otherwise
+	LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
+	if (floater_container->getConversationListItemSize() == 1)
 	{
-		llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : hosted -> do nothing" << llendl;
+		floater_container->closeFloater();
 	}
 	else
 	{
-		llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : close floater " << llendl;
-		LLFloater::closeFloater();
+		if (!getHost())
+		{
+			setVisible(FALSE);
+		}
+		floater_container->selectNextConversation(LLUUID());
 	}
 }
 
diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h
index 2d32bb3fc9..2992c12436 100644
--- a/indra/newview/llfloaterimnearbychat.h
+++ b/indra/newview/llfloaterimnearbychat.h
@@ -54,7 +54,6 @@ public:
 	/*virtual*/ void onOpen(const LLSD& key);
 	/*virtual*/ void onClose(bool app_quitting);
 	/*virtual*/ void setVisible(BOOL visible);
-	/*virtual*/ void closeFloater(bool app_quitting = false);
 	/*virtual*/ void closeHostedFloater();
 
 	void loadHistory();
-- 
cgit v1.2.3