void LLNearbyChatScreenChannel::deactivateToast(LLToast* toast)
{
	toast_vec_t::iterator pos = std::find(m_active_toasts.begin(), m_active_toasts.end(), toast->getHandle());

	if (pos == m_active_toasts.end())
	{
		llassert(pos == m_active_toasts.end());
		return;
	}

	LL_DEBUGS("NearbyChat") << "Deactivating toast" << llendl;
	m_active_toasts.erase(pos);
}
void LLNearbyChatScreenChannel::showToastsBottom()
{
	if(mStopProcessing)
		return;

	LLRect	toast_rect;	
	updateBottom();
	S32 channel_bottom = getRect().mBottom;

	S32		bottom = channel_bottom;
	S32		margin = gSavedSettings.getS32("ToastGap");

	//sort active toasts
	std::sort(m_active_toasts.begin(),m_active_toasts.end(),sort_toasts_predicate);

	//calc max visible item and hide other toasts.

	for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
	{
		LLToast* toast = it->get();
		if (!toast)
		{
			llwarns << "NULL found in the active chat toasts list!" << llendl;
			continue;
		}

		S32 toast_top = bottom + toast->getRect().getHeight() + margin;

		if(toast_top > gFloaterView->getRect().getHeight())
		{
			while(it!=m_active_toasts.end())
			{
				addToToastPool(it->get());
				it=m_active_toasts.erase(it);
			}
			break;
		}

		toast_rect = toast->getRect();
		toast_rect.setLeftTopAndSize(getRect().mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight());

		toast->setRect(toast_rect);
		bottom += toast_rect.getHeight() - toast->getTopPad() + margin;
	}
	
	// use reverse order to provide correct z-order and avoid toast blinking
	
	for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it)
	{
		LLToast* toast = it->get();
		if (toast)
	{
		toast->setIsHidden(false);
		toast->setVisible(TRUE);
		}
	}

	}
void LLNearbyChatScreenChannel::updateSize(LLRect old_world_rect, LLRect new_world_rect)
{
	for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
	{
		LLToast* toast = it->get();

		if (toast)
		{
			LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());

			if(panel)
			{
				reshapePanel(panel);
				toast->reshapeToPanel();
			}
		}
	}
	arrangeToasts();
}
void LLNearbyChatScreenChannel::arrangeToasts()
{
	if(!isHovering())
	{
		showToastsBottom();
	}

	if (m_active_toasts.empty())
	{
		LLHints::registerHintTarget("incoming_chat", LLHandle<LLView>());
	}
	else
	{
		LLToast* toast = m_active_toasts.front().get();
		if (toast)
		{
			LLHints::registerHintTarget("incoming_chat", m_active_toasts.front().get()->LLView::getHandle());
		}
	}
}
void LLNearbyChatScreenChannel::arrangeToasts()
{
	if(mStopProcessing || isHovering())
		return;

	if (mFloaterSnapRegion == NULL)
	{
		mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region");
	}
	
	if (!getParent())
	{
		// connect to floater snap region just to get resize events, we don't care about being a proper widget 
		mFloaterSnapRegion->addChild(this);
		setFollows(FOLLOWS_ALL);
	}

	LLRect	toast_rect;	
	updateRect();

	LLRect channel_rect;
	mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &channel_rect, gFloaterView);
	channel_rect.mLeft += 10;
	channel_rect.mRight = channel_rect.mLeft + 300;

	S32 channel_bottom = channel_rect.mBottom;

	// <FS:Ansariel> Configurable nearby chat toasts offset
	//S32		bottom = channel_bottom + 80;
	S32		bottom = channel_bottom + gSavedSettings.getS32("FSNearbyChatToastsOffset");
	S32		margin = gSavedSettings.getS32("ToastGap");

	//sort active toasts
	std::sort(m_active_toasts.begin(),m_active_toasts.end(),sort_toasts_predicate);

	//calc max visible item and hide other toasts.

	for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
	{
		LLToast* toast = it->get();
		if (!toast)
		{
			llwarns << "NULL found in the active chat toasts list!" << llendl;
			continue;
		}

		S32 toast_top = bottom + toast->getRect().getHeight() + margin;

		if(toast_top > channel_rect.getHeight())
		{
			while(it!=m_active_toasts.end())
			{
				addToToastPool(it->get());
				it=m_active_toasts.erase(it);
			}
			break;
		}

		toast_rect = toast->getRect();
		toast_rect.setLeftTopAndSize(channel_rect.mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight());

		toast->setRect(toast_rect);
		bottom += toast_rect.getHeight() - toast->getTopPad() + margin;
	}
	
	// use reverse order to provide correct z-order and avoid toast blinking
	
	for(toast_vec_t::reverse_iterator it = m_active_toasts.rbegin(); it != m_active_toasts.rend(); ++it)
	{
		LLToast* toast = it->get();
		if (toast)
		{
		toast->setIsHidden(false);
		toast->setVisible(TRUE);
		}
	}

}
void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
{
	//look in pool. if there is any message
	if(mStopProcessing)
		return;

	/*
    find last toast and check ID
	*/

	if(m_active_toasts.size())
	{
		LLUUID fromID = notification["from_id"].asUUID();		// agent id or object id
		std::string from = notification["from"].asString();
		LLToast* toast = m_active_toasts[0].get();
		if (toast)
		{
			LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());
  
			if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())
			{
				panel->addMessage(notification);
				reshapePanel(panel);
				toast->reshapeToPanel();
				toast->startTimer();
	  
				arrangeToasts();
				return;
			}
		}
	}
	

	
	if(m_toast_pool.empty())
	{
		//"pool" is empty - create one more panel
		LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;
		if(!createPoolToast())//created toast will go to pool. so next call will find it
			return;
		addNotification(notification);
		return;
	}

	int chat_type = notification["chat_type"].asInteger();
	
	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))
	{
		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) 
			return;
		if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)
			return;
	}
		

	//take 1st element from pool, (re)initialize it, put it in active toasts

	LL_DEBUGS("NearbyChat") << "Getting toast from pool" << llendl;
	LLToast* toast = m_toast_pool.back().get();

	m_toast_pool.pop_back();


	LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel());
	if(!panel)
		return;
	panel->init(notification);

	reshapePanel(panel);
	toast->reshapeToPanel();
	toast->startTimer();
	
	m_active_toasts.push_back(toast->getHandle());

	arrangeToasts();
}