From 0312156258f962108ce485c4be95992555b09b32 Mon Sep 17 00:00:00 2001
From: Dmitry Zaporozhan <dzaporozhan@productengine.com>
Date: Fri, 25 Dec 2009 13:53:11 +0200
Subject: [PATCH] Fixed low bug EXT-3294 - Toasts bunch up in the channel when
 big docked IM window is opened.

--HG--
branch : product-engine
---
 indra/llui/lldockablefloater.cpp  |  1 +
 indra/llui/lldockablefloater.h    | 10 +++++
 indra/newview/llimfloater.cpp     |  1 +
 indra/newview/llscreenchannel.cpp | 69 ++++++++++++++++++++++++-------
 indra/newview/llscreenchannel.h   |  2 +
 indra/newview/llscriptfloater.cpp |  1 +
 indra/newview/llsyswellwindow.cpp |  1 +
 7 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 63faf44f9dc..6a5b475134b 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -54,6 +54,7 @@ void LLDockableFloater::init(LLDockableFloater* thiz)
 LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
 		const LLSD& key, const Params& params) :
 	LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true)
+	, mOverlapsScreenChannel(false)
 {
 	init(this);
 }
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 2c339f4a3f5..2c0a484cc88 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -85,6 +85,14 @@ class LLDockableFloater : public LLFloater
 
 	LLDockControl* getDockControl();
 
+	/**
+	 * Returns true if screen channel should consider floater's size when drawing toasts.
+	 *
+	 * By default returns false.
+	 */
+	virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); }
+	virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; }
+
 private:
 	/**
 	 * Provides unique of dockable floater.
@@ -105,6 +113,8 @@ class LLDockableFloater : public LLFloater
 	 *  non exclusively.
 	 */
 	bool mUniqueDocking;
+
+	bool mOverlapsScreenChannel;
 };
 
 #endif /* LL_DOCKABLEFLOATER_H */
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 0ce8d4b7cdf..259f629bdd3 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -109,6 +109,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 		default: break;
 		}
 	}
+	setOverlapsScreenChannel(true);
 }
 
 void LLIMFloater::onFocusLost()
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index c18fe8ad7e9..8c3f3dc5fb8 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -462,6 +462,8 @@ void LLScreenChannel::showToastsBottom()
 	S32		toast_margin = 0;
 	std::vector<ToastElem>::reverse_iterator it;
 
+	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
+
 	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
 	{
 		if(it != mToastList.rbegin())
@@ -474,6 +476,16 @@ void LLScreenChannel::showToastsBottom()
 		toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight());
 		(*it).toast->setRect(toast_rect);
 
+		// don't show toasts if there is not enough space
+		if(floater && floater->overlapsScreenChannel())
+		{
+			LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+			if(toast_rect.mTop + getOverflowToastHeight() + toast_margin > world_rect.mTop)
+			{
+				break;
+			}
+		}
+
 		bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;
 
 		if(!stop_showing_toasts)
@@ -575,6 +587,18 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
 	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());	
 	mOverflowToastPanel->setRect(toast_rect);
 
+	// don't show overflow toast if there is not enough space for it.
+	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
+	if(floater && floater->overlapsScreenChannel())
+	{
+		LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+		if(toast_rect.mTop > world_rect.mTop)
+		{
+			closeOverflowToastPanel();
+			return;
+		}
+	}
+
 	text_box->setValue(text);
 	text_box->setVisible(TRUE);
 
@@ -664,6 +688,24 @@ F32 LLScreenChannel::getHeightRatio()
 	return ratio;
 }
 
+S32 LLScreenChannel::getOverflowToastHeight()
+{
+	if(mOverflowToastPanel)
+	{
+		return mOverflowToastPanel->getRect().getHeight();
+	}
+
+	static S32 height = 0;
+	if(0 == height)
+	{
+		LLToast::Params p;
+		LLToast* toast = new LLToast(p);
+		height = toast->getRect().getHeight();
+		delete toast;
+	}
+	return height;
+}
+
 //--------------------------------------------------------------------------
 void LLScreenChannel::updateStartUpString(S32 num)
 {
@@ -822,25 +864,22 @@ void LLScreenChannel::updateShowToastsState()
 		return;
 	}
 
-	// for Message Well floater showed in a docked state - adjust channel's height
-	if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater)
-		|| dynamic_cast<LLScriptFloater*>(floater))
+	S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
+	LLRect this_rect = getRect();
+
+	// adjust channel's height
+	if(floater->overlapsScreenChannel())
 	{
-		S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
-		LLRect this_rect = getRect();
-		if(floater->getVisible() && floater->isDocked())
+		channel_bottom += floater->getRect().getHeight();
+		if(floater->getDockControl())
 		{
-			channel_bottom += floater->getRect().getHeight();
-			if(floater->getDockControl())
-			{
-				channel_bottom += floater->getDockControl()->getTongueHeight();
-			}
+			channel_bottom += floater->getDockControl()->getTongueHeight();
 		}
+	}
 
-		if(channel_bottom != this_rect.mBottom)
-		{
-			setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));
-		}
+	if(channel_bottom != this_rect.mBottom)
+	{
+		setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));
 	}
 }
 
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index 321fb244a1b..38f27f756b6 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -281,6 +281,8 @@ class LLScreenChannel : public LLScreenChannelBase
 	 */
 	static F32 getHeightRatio();
 
+	S32 getOverflowToastHeight();
+
 	// Channel's flags
 	static bool	mWasStartUpToastShown;
 
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 1962d871a6b..cf62d473620 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -67,6 +67,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key)
 , mScriptForm(NULL)
 {
 	setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this));
+	setOverlapsScreenChannel(true);
 }
 
 bool LLScriptFloater::toggle(const LLUUID& object_id)
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 3cddf6d902c..bcaefc36909 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -63,6 +63,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key)
 {
 	mTypedItemsCount[IT_NOTIFICATION] = 0;
 	mTypedItemsCount[IT_INSTANT_MESSAGE] = 0;
+	setOverlapsScreenChannel(true);
 }
 
 //---------------------------------------------------------------------------------
-- 
GitLab