diff options
| author | Richard Linden <none@none> | 2012-05-18 13:20:32 -0700 | 
|---|---|---|
| committer | Richard Linden <none@none> | 2012-05-18 13:20:32 -0700 | 
| commit | 296e55c1b323c05b6544b69ace04afe19102396b (patch) | |
| tree | a0d3a495061442b2adfb4342c5c490c039526489 | |
| parent | cf86247b8c5e199447b7cd3dc645a42a6a645265 (diff) | |
CHUI-112 FIX Clicking Show or Discard in an inventory offer toast does not dismiss toast
removed special case logic for dealing with user online/offline collisions
added ability to cancel old duplicate notifications
27 files changed, 721 insertions, 715 deletions
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 9ef9b4bbec..663749b983 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -60,7 +60,8 @@ void NotificationPriorityValues::declareValues()  }  LLNotificationForm::FormElementBase::FormElementBase() -:	name("name") +:	name("name"), +	enabled("enabled", true)  {}  LLNotificationForm::FormIgnore::FormIgnore() @@ -210,6 +211,14 @@ LLNotificationForm::LLNotificationForm()  {  } +LLNotificationForm::LLNotificationForm( const LLNotificationForm& other ) +{ +	mFormData 	   = other.mFormData; +	mIgnore 	   = other.mIgnore; +	mIgnoreMsg 	   = other.mIgnoreMsg; +	mIgnoreSetting = other.mIgnoreSetting; +	mInvertSetting = other.mInvertSetting; +}  LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p)   :	mIgnore(IGNORE_NO), @@ -300,7 +309,7 @@ LLSD LLNotificationForm::getElement(const std::string& element_name)  } -bool LLNotificationForm::hasElement(const std::string& element_name) +bool LLNotificationForm::hasElement(const std::string& element_name) const  {  	for (LLSD::array_const_iterator it = mFormData.beginArray();  		it != mFormData.endArray(); @@ -311,7 +320,36 @@ bool LLNotificationForm::hasElement(const std::string& element_name)  	return false;  } -void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value) +bool LLNotificationForm::getElementEnabled(const std::string& element_name) const +{ +	for (LLSD::array_const_iterator it = mFormData.beginArray(); +		it != mFormData.endArray(); +		++it) +	{ +		if ((*it)["name"].asString() == element_name) +		{ +			return (*it)["enabled"].asBoolean(); +		} +	} + +	return false; +} + +void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled) +{ +	for (LLSD::array_iterator it = mFormData.beginArray(); +		it != mFormData.endArray(); +		++it) +	{ +		if ((*it)["name"].asString() == element_name) +		{ +			(*it)["enabled"] = enabled; +		} +	} +} + + +void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled)  {  	LLSD element;  	element["type"] = type; @@ -319,6 +357,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string&  	element["text"] = name;  	element["value"] = value;  	element["index"] = mFormData.size(); +	element["enabled"] = enabled;  	mFormData.append(element);  } @@ -412,7 +451,8 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par  	mPersist(p.persist),  	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()),  	mLogToChat(p.log_to_chat), -	mLogToIM(p.log_to_im) +	mLogToIM(p.log_to_im), +	mShowToast(p.show_toast)  {  	if (p.sound.isProvided()  		&& LLUI::sSettingGroups["config"]->controlExists(p.sound)) @@ -571,7 +611,6 @@ void LLNotification::updateFrom(LLNotificationPtr other)  	mRespondedTo = other->mRespondedTo;  	mResponse = other->mResponse;  	mTemporaryResponder = other->mTemporaryResponder; -	mIsReusable = other->isReusable();  	update();  } @@ -670,7 +709,7 @@ void LLNotification::respond(const LLSD& response)  		return;  	} -	if (mTemporaryResponder && !isReusable()) +	if (mTemporaryResponder)  	{  		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);  		mResponseFunctorName = ""; @@ -899,6 +938,11 @@ bool LLNotification::canLogToIM() const  	return mTemplatep->mLogToIM;  } +bool LLNotification::canShowToast() const +{ +	return mTemplatep->mShowToast; +} +  bool LLNotification::hasFormElements() const  {  	return mTemplatep->mForm->getNumElements() != 0; @@ -909,6 +953,17 @@ LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const  	return mTemplatep->mCombineBehavior;  } +void LLNotification::updateForm( const LLNotificationFormPtr& form ) +{ +	mForm = form; +} + +void LLNotification::repost() +{ +	mRespondedTo = false; +	LLNotifications::instance().update(shared_from_this()); +} +  // ========================================================= @@ -1065,12 +1120,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		if (wasFound)  		{  			abortProcessing = mChanged(payload); -			// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window -			if( ! pNotification->isReusable() ) -			{ -				mItems.erase(pNotification); -				onDelete(pNotification); -			} +			mItems.erase(pNotification); +			onDelete(pNotification);  		}  	}  	return abortProcessing; @@ -1207,7 +1258,15 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)  		if (pNotif != existing_notification   			&& pNotif->isEquivalentTo(existing_notification))  		{ -			return false; +			if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD) +			{ +				cancel(existing_notification); +				return true; +			} +			else +			{ +				return false; +			}  		}  	} @@ -1247,26 +1306,35 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)  		return false;  	} -	if (pNotif->getCombineBehavior() == LLNotification::USE_NEWEST) -	{ -	// Update the existing unique notification with the data from this particular instance... -	// This guarantees that duplicate notifications will be collapsed to the one -	// most recently triggered -	for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); -		existing_it != mUniqueNotifications.end(); -		++existing_it) +	switch(pNotif->getCombineBehavior())  	{ -		LLNotificationPtr existing_notification = existing_it->second; -		if (pNotif != existing_notification  -			&& pNotif->isEquivalentTo(existing_notification)) +	case  LLNotification::REPLACE_WITH_NEW: +		// Update the existing unique notification with the data from this particular instance... +		// This guarantees that duplicate notifications will be collapsed to the one +		// most recently triggered +		for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); +			existing_it != mUniqueNotifications.end(); +			++existing_it)  		{ -			// copy notification instance data over to oldest instance -			// of this unique notification and update it -			existing_notification->updateFrom(pNotif); -			// then delete the new one -			cancel(pNotif); +			LLNotificationPtr existing_notification = existing_it->second; +			if (pNotif != existing_notification  +				&& pNotif->isEquivalentTo(existing_notification)) +			{ +				// copy notification instance data over to oldest instance +				// of this unique notification and update it +				existing_notification->updateFrom(pNotif); +				// then delete the new one +				cancel(pNotif); +			}  		} -	} +		break; +	case LLNotification::KEEP_OLD: +		break; +	case LLNotification::CANCEL_OLD: +		// already handled by filter logic +		break; +	default: +		break;  	}  	return false; @@ -1594,12 +1662,11 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)  	if (pNotif == NULL || pNotif->isCancelled()) return;  	LLNotificationSet::iterator it=mItems.find(pNotif); -	if (it == mItems.end()) +	if (it != mItems.end())  	{ -		llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl; +		pNotif->cancel(); +		updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);  	} -	pNotif->cancel(); -	updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);  }  void LLNotifications::cancelByName(const std::string& name) diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 21a4318aab..e9449eae69 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -165,6 +165,7 @@ public:  	struct FormElementBase : public LLInitParam::Block<FormElementBase>  	{  		Optional<std::string>	name; +		Optional<bool>			enabled;  		FormElementBase();  	}; @@ -234,16 +235,20 @@ public:  	} EIgnoreType;  	LLNotificationForm(); +	LLNotificationForm(const LLNotificationForm&);  	LLNotificationForm(const LLSD& sd);  	LLNotificationForm(const std::string& name, const Params& p); +	void fromLLSD(const LLSD& sd);  	LLSD asLLSD() const;  	S32 getNumElements() { return mFormData.size(); }  	LLSD getElement(S32 index) { return mFormData.get(index); }  	LLSD getElement(const std::string& element_name); -	bool hasElement(const std::string& element_name); -	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD()); +	bool hasElement(const std::string& element_name) const; +	bool getElementEnabled(const std::string& element_name) const; +	void setElementEnabled(const std::string& element_name, bool enabled); +	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true);  	void formatElements(const LLSD& substitutions);  	// appends form elements from another form serialized as LLSD  	void append(const LLSD& sub_form); @@ -450,6 +455,11 @@ public:  	// ["responseFunctor"] = name of registered functor that handles responses to notification;  	LLSD asLLSD(); +	const LLNotificationFormPtr getForm(); +	void updateForm(const LLNotificationFormPtr& form); + +	void repost(); +  	void respond(const LLSD& sd);  	void respondWithDefault(); @@ -517,16 +527,18 @@ public:      S32 getURLOpenExternally() const;  	bool canLogToChat() const;  	bool canLogToIM() const; +	bool canShowToast() const;  	bool hasFormElements() const;  	typedef enum e_combine_behavior  	{ -		USE_NEWEST, -		USE_OLDEST +		REPLACE_WITH_NEW, +		KEEP_OLD, +		CANCEL_OLD +  	} ECombineBehavior;  	ECombineBehavior getCombineBehavior() const; -	const LLNotificationFormPtr getForm();  	const LLDate getExpiration() const  	{ @@ -545,8 +557,6 @@ public:  	bool isReusable() { return mIsReusable; } -	void setReusable(bool reusable) { mIsReusable = reusable; } -	  	// comparing two notifications normally means comparing them by UUID (so we can look them  	// up quickly this way)  	bool operator<(const LLNotification& rhs) const diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index f7d08ae1f4..ca9c4294c1 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -66,8 +66,9 @@ struct LLNotificationTemplate  	{  		static void declareValues()  		{ -			declare("newest", LLNotification::USE_NEWEST); -			declare("oldest", LLNotification::USE_OLDEST); +			declare("replace_with_new", LLNotification::REPLACE_WITH_NEW); +			declare("keep_old", LLNotification::KEEP_OLD); +			declare("cancel_old", LLNotification::CANCEL_OLD);  		}  	}; @@ -109,7 +110,7 @@ struct LLNotificationTemplate  		UniquenessConstraint()  		:	contexts("context"), -			combine("combine", LLNotification::USE_NEWEST), +			combine("combine", LLNotification::REPLACE_WITH_NEW),  			dummy_val("")  		{}  	}; @@ -185,6 +186,7 @@ struct LLNotificationTemplate  		Mandatory<std::string>			name;  		Optional<bool>					persist,  										log_to_im, +										show_toast,  										log_to_chat;  		Optional<std::string>			functor,  										icon, @@ -206,6 +208,7 @@ struct LLNotificationTemplate  		:	name("name"),  			persist("persist", false),  			log_to_im("log_to_im", false), +			show_toast("show_toast", true),  			log_to_chat("log_to_chat", true),  			functor("functor"),  			icon("icon"), @@ -313,6 +316,7 @@ struct LLNotificationTemplate  	// inject these notifications into chat/IM streams  	bool mLogToChat;  	bool mLogToIM; +	bool mShowToast;  };  #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index ac14ec2cc0..aa626a9a30 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -1024,7 +1024,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri  	LLSD payload;  	payload["from_id"] = target_id; -	payload["SUPPRESS_TOAST"] = true;  	LLNotificationsUtil::add("FriendshipOffered", args, payload);  } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0d55c4429a..60d60abd45 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -54,6 +54,7 @@  #include "llresmgr.h"  #include "llslurl.h"  #include "llimview.h" +#include "lltrans.h"  #include "llviewercontrol.h"  #include "llviewernetwork.h"  #include "llviewerobjectlist.h" @@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	// Use display name only because this user is your friend  	LLSD args;  	args["NAME"] = av_name.mDisplayName; +	args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus");  	LLNotificationPtr notification;  	if (online)  	{  		notification = -			LLNotificationsUtil::add("FriendOnline", +			LLNotificationsUtil::add("FriendOnlineOffline",  									 args,  									 payload.with("respond_on_mousedown", TRUE),  									 boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	else  	{  		notification = -			LLNotificationsUtil::add("FriendOffline", args, payload); +			LLNotificationsUtil::add("FriendOnlineOffline", args, payload);  	}  	// If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 5bdfb5adbc..3da868945b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -877,35 +877,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		if (notification != NULL)  		{  			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( -					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); -			//we can't set follows in xml since it broke toasts behavior -			notify_box->setFollowsLeft(); -			notify_box->setFollowsRight(); -			notify_box->setFollowsTop(); - -			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); -			S32 offset = 0; -			// Children were added by addChild() which uses push_front to insert them into list, -			// so to get buttons in correct order reverse iterator is used (EXT-5906)  -			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) -			{ -				LLButton * button = dynamic_cast<LLButton*> (*it); -				if (button != NULL) -				{ -					button->setOrigin( offset, -							button->getRect().mBottom); -					button->setLeftHPad(2 * HPAD); -					button->setRightHPad(2 * HPAD); -					// set zero width before perform autoResize() -					button->setRect(LLRect(button->getRect().mLeft, -							button->getRect().mTop, button->getRect().mLeft, -							button->getRect().mBottom)); -					button->setAutoResize(true); -					button->autoResize(); -					offset += HPAD + button->getRect().getWidth(); -					button->setFollowsNone(); -				} -			} +					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor);  			//Prepare the rect for the view  			LLRect target_rect = mEditor->getDocumentView()->getRect(); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9a84280f25..7477fbd656 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -372,7 +372,6 @@ void LLNearbyChatToastPanel::draw()  		}  		mIsDirty = false;  	} -	LLToastPanelBase::draw();  } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 1d700dcede..89b0c4f37a 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,7 +40,7 @@ typedef enum e_show_item_header  	CHATITEMHEADER_SHOW_BOTH  } EShowItemHeader; -class LLNearbyChatToastPanel: public LLToastPanelBase +class LLNearbyChatToastPanel : public LLPanel  {  protected:          LLNearbyChatToastPanel() diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f67464078b..724ae3c25e 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -56,6 +56,7 @@  #include "llrootview.h"  #include "llspeakers.h"  #include "llviewerchat.h" +#include "llnotificationmanager.h"  LLIMFloater::LLIMFloater(const LLUUID& session_id) diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 4d9db01e0d..f26cc85019 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -1,6 +1,6 @@  /**    * @file LLNearbyChatHandler.cpp - * @brief Nearby chat notification managment + * @brief Nearby chat chat managment   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code @@ -47,15 +47,17 @@  //add LLNearbyChatHandler to LLNotificationsUI namespace  using namespace LLNotificationsUI; -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//-----------------------------------------------------------------------------------------------	 -LLToastPanelBase* createToastPanel() +static LLNearbyChatToastPanel* createToastPanel()  {  	LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();  	return item;  } + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//-----------------------------------------------------------------------------------------------	 +  class LLNearbyChatScreenChannel: public LLScreenChannelBase  {  	LOG_CLASS(LLNearbyChatScreenChannel); @@ -81,10 +83,10 @@ public:  		}  	} -	void addNotification	(LLSD& notification); +	void addChat	(LLSD& chat);  	void arrangeToasts		(); -	typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; +	typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t;  	void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}  	void onToastDestroyed	(LLToast* toast, bool app_quitting); @@ -152,6 +154,8 @@ protected:  	bool	mChannelRect;  }; + +  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast  //----------------------------------------------------------------------------------------------- @@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime()  bool	LLNearbyChatScreenChannel::createPoolToast()  { -	LLToastPanelBase* panel= m_create_toast_panel_callback_t(); +	LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t();  	if(!panel)  		return false; @@ -277,7 +281,7 @@ bool	LLNearbyChatScreenChannel::createPoolToast()  	return true;  } -void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +void LLNearbyChatScreenChannel::addChat(LLSD& chat)  {  	//look in pool. if there is any message  	if(mStopProcessing) @@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	if(m_active_toasts.size())  	{ -		LLUUID fromID = notification["from_id"].asUUID();		// agent id or object id -		std::string from = notification["from"].asString(); +		LLUUID fromID = chat["from_id"].asUUID();		// agent id or object id +		std::string from = chat["from"].asString();  		LLToast* toast = m_active_toasts[0].get();  		if (toast)  		{ @@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  			if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())  			{ -				panel->addMessage(notification); +				panel->addMessage(chat);  				toast->reshapeToPanel();  				toast->startTimer(); @@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  		LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;  		if(!createPoolToast())//created toast will go to pool. so next call will find it  			return; -		addNotification(notification); +		addChat(chat);  		return;  	} -	int chat_type = notification["chat_type"].asInteger(); +	int chat_type = chat["chat_type"].asInteger();  	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))  	{ @@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	m_toast_pool.pop_back(); -	LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); +	LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());  	if(!panel)  		return; -	panel->init(notification); +	panel->init(chat);  	toast->reshapeToPanel();  	toast->startTimer(); @@ -488,23 +492,23 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat");  	// Build notification data  -	LLSD notification; -	notification["message"] = chat_msg.mText; -	notification["from"] = chat_msg.mFromName; -	notification["from_id"] = chat_msg.mFromID; -	notification["time"] = chat_msg.mTime; -	notification["source"] = (S32)chat_msg.mSourceType; -	notification["chat_type"] = (S32)chat_msg.mChatType; -	notification["chat_style"] = (S32)chat_msg.mChatStyle; +	LLSD chat; +	chat["message"] = chat_msg.mText; +	chat["from"] = chat_msg.mFromName; +	chat["from_id"] = chat_msg.mFromID; +	chat["time"] = chat_msg.mTime; +	chat["source"] = (S32)chat_msg.mSourceType; +	chat["chat_type"] = (S32)chat_msg.mChatType; +	chat["chat_style"] = (S32)chat_msg.mChatStyle;  	// Pass sender info so that it can be rendered properly (STORM-1021). -	notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); +	chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);  	if (chat_msg.mChatType == CHAT_TYPE_DIRECT &&  		chat_msg.mText.length() > 0 &&  		chat_msg.mText[0] == '@')  	{  		// Send event on to LLEventStream and exit -		sChatWatcher->post(notification); +		sChatWatcher->post(chat);  		return;  	} @@ -551,7 +555,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	}  	// Send event on to LLEventStream -	sChatWatcher->post(notification); +	sChatWatcher->post(chat);  	if( !chat_bar->isMinimized() @@ -602,16 +606,16 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  		// Add a nearby chat toast.  		LLUUID id;  		id.generate(); -		notification["id"] = id; +		chat["id"] = id;  		std::string r_color_name = "White";  		F32 r_color_alpha = 1.0f;   		LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); -		notification["text_color"] = r_color_name; -		notification["color_alpha"] = r_color_alpha; -		notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ; -		notification["message"] = toast_msg; -		channel->addNotification(notification);	 +		chat["text_color"] = r_color_name; +		chat["color_alpha"] = r_color_alpha; +		chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; +		chat["message"] = toast_msg; +		channel->addChat(chat);	  	}  } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 6946b78cbf..18cd94e685 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -44,7 +44,6 @@ LLGroupHandler::LLGroupHandler()  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -94,16 +93,6 @@ bool LLGroupHandler::processNotification(const LLNotificationPtr& notification)  	return false;  } -//-------------------------------------------------------------------------- -void LLGroupHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification && mItems.find(notification) != mItems.end()) -	{ -		LLNotifications::instance().cancel(notification); -	} -}  //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 83d228e799..4d54bb78fc 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -95,16 +95,9 @@ public:  	// base interface functions  	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); }  	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } -	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->killToastByNotificationID(p->getID());} +	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());}  	virtual bool processNotification(const LLNotificationPtr& notify)=0; - -protected : -	static void init(); -	void removeExclusiveNotifications(const LLNotificationPtr& notif); - -	typedef std::list< std::set<std::string> > exclusive_notif_sets; -	static exclusive_notif_sets sExclusiveNotificationGroups;  };  /** @@ -148,7 +141,6 @@ public:  	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	/*virtual*/ void onRejectToast(const LLUUID& id);  	/*virtual*/ void initChannel();  }; @@ -169,9 +161,6 @@ public:  protected:  	/*virtual*/ void onDeleteToast(LLToast* toast);  	/*virtual*/ void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id);  }; @@ -190,9 +179,6 @@ public:  protected:  	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id);  };  /** @@ -225,15 +211,12 @@ public:  	virtual ~LLOfferHandler();  	// base interface functions -	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p);  	/*virtual*/ void onDelete(LLNotificationPtr notification);  	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected:  	/*virtual*/ void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id);  };  /** diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 1494ac6b5c..cba22b233b 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,75 +41,9 @@  using namespace LLNotificationsUI; -// static -std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups; - -// static -void LLSysHandler::init() -{ -	std::set<std::string> online_offline_group; -	online_offline_group.insert("FriendOnline"); -	online_offline_group.insert("FriendOffline"); - -	sExclusiveNotificationGroups.push_back(online_offline_group); -} -  LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type)  :	LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) -{ -	if(sExclusiveNotificationGroups.empty()) -	{ -		init(); -	} -} - -void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) -{ -	LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); -	if (channel == NULL) -	{ -		return; -	} - -	class ExclusiveMatcher: public LLScreenChannel::Matcher -	{ -	public: -		ExclusiveMatcher(const std::set<std::string>& excl_group, -				const std::string& from_name) : -			mExclGroup(excl_group), mFromName(from_name) -		{ -		} -		bool matches(const LLNotificationPtr notification) const -		{ -			for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it -					!= mExclGroup.end(); it++) -			{ -				std::string from_name = LLHandlerUtil::getSubstitutionName(notification); -				if (notification->getName() == *it && from_name == mFromName) -				{ -					return true; -				} -			} -			return false; -		} -	private: -		const std::set<std::string>& mExclGroup; -		const std::string& mFromName; -	}; - - -	for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it -			!= sExclusiveNotificationGroups.end(); it++) -	{ -		std::set<std::string> group = *it; -		std::set<std::string>::iterator g_it = group.find(notif->getName()); -		if (g_it != group.end()) -		{ -			channel->killMatchedToasts(ExclusiveMatcher(group, -					LLHandlerUtil::getSubstitutionName(notif))); -		} -	} -} +{}  // static  bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 2112b0d35e..6e641575fa 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -48,7 +48,6 @@ LLOfferHandler::LLOfferHandler()  	if(channel)  	{  		channel->setControlHovering(true); -		channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -81,92 +80,95 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)  	} -		if( notification->getPayload().has("give_inventory_notification") +	if( notification->getPayload().has("give_inventory_notification")  		&& notification->getPayload()["give_inventory_notification"].asBoolean() == false) -		{ -			// This is an original inventory offer, so add a script floater -			LLScriptFloaterManager::instance().onAddNotification(notification->getID()); -		} -		else -		{ +	{ +		// This is an original inventory offer, so add a script floater +		LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +	} +	else +	{  		bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); -		notification->setReusable(add_notif_to_im); - -			LLUUID session_id;  		if (add_notif_to_im) -			{ -				const std::string name = LLHandlerUtil::getSubstitutionName(notification); +		{ +			const std::string name = LLHandlerUtil::getSubstitutionName(notification); -				LLUUID from_id = notification->getPayload()["from_id"]; +			LLUUID from_id = notification->getPayload()["from_id"]; -				session_id = LLHandlerUtil::spawnIMSession(name, from_id); -				LLHandlerUtil::addNotifPanelToIM(notification); -			} +			LLHandlerUtil::spawnIMSession(name, from_id); +			LLHandlerUtil::addNotifPanelToIM(notification); +		} -			if (notification->getPayload().has("SUPPRESS_TOAST") -						&& notification->getPayload()["SUPPRESS_TOAST"]) -			{ -				LLNotificationsUtil::cancel(notification); -			} +		if (!notification->canShowToast()) +		{ +			LLNotificationsUtil::cancel(notification); +		}  		else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification)) -			{ -				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); -				// don't close notification on panel destroy since it will be used by IM floater -			notify_box->setCloseNotificationOnDestroy(!add_notif_to_im); -				LLToast::Params p; -				p.notif_id = notification->getID(); -				p.notification = notification; -				p.panel = notify_box; -				// we not save offer notifications to the syswell floater that should be added to the IM floater +		{ +			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); +			LLToast::Params p; +			p.notif_id = notification->getID(); +			p.notification = notification; +			p.panel = notify_box; +			// we not save offer notifications to the syswell floater that should be added to the IM floater  			p.can_be_stored = !add_notif_to_im; -				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -				if(channel) -					channel->addToast(p); -			} +			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +			if(channel) +				channel->addToast(p); +		}  		if (notification->canLogToIM()) -			{ -				// log only to file if notif panel can be embedded to IM and IM is opened +		{ +			// log only to file if notif panel can be embedded to IM and IM is opened  			bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification);  			LLHandlerUtil::logToIMP2P(notification, file_only); -				} -				} +		} +	}  	return false; -			} +} -/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p) +{ +	LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); +	if (panelp)  	{ -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		// +		// HACK: if we're dealing with a notification embedded in IM, update it +		// otherwise remove its toast +		// +		if (dynamic_cast<LLIMToastNotifyPanel*>(panelp))  		{ -			// Remove original inventory offer script floater -			LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +			panelp->updateNotification();  		}  		else  		{ -		if (notification->canLogToIM()  -			&& notification->hasFormElements() -					&& !LLHandlerUtil::isIMFloaterOpened(notification)) -			{ -				LLHandlerUtil::decIMMesageCounter(notification); -			} -			mChannel.get()->killToastByNotificationID(notification->getID()); +			// if notification has changed, hide it +			mChannel.get()->removeToastByNotificationID(p->getID());  		}  	} +} -//-------------------------------------------------------------------------- -void LLOfferHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); -	if (notification -		&& mItems.find(notification) != mItems.end() -					// don't delete notification since it may be used by IM floater -		&& (!notification->canLogToIM() || !notification->hasFormElements())) +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ +	if( notification->getPayload().has("give_inventory_notification") +		&& !notification->getPayload()["give_inventory_notification"] ) +	{ +		// Remove original inventory offer script floater +		LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +	} +	else  	{ -		LLNotifications::instance().cancel(notification); +		if (notification->canLogToIM()  +			&& notification->hasFormElements() +			&& !LLHandlerUtil::isIMFloaterOpened(notification)) +		{ +			LLHandlerUtil::decIMMesageCounter(notification); +		} +		mChannel.get()->removeToastByNotificationID(notification->getID());  	}  } + diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 8472f9b2ae..9f7d0cc2f5 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -46,7 +46,6 @@ LLScriptHandler::LLScriptHandler()  	if(channel)  	{  		channel->setControlHovering(true); -		channel->addOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -116,7 +115,7 @@ void LLScriptHandler::onDelete( LLNotificationPtr notification )  		}  		else  		{ -			mChannel.get()->killToastByNotificationID(notification->getID()); +			mChannel.get()->removeToastByNotificationID(notification->getID());  		}  	} @@ -135,19 +134,6 @@ void LLScriptHandler::onDeleteToast(LLToast* toast)  	}  } -//-------------------------------------------------------------------------- -void LLScriptHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification && mItems.find(notification) != mItems.end()) -	{ -		LLNotifications::instance().cancel(notification); -	} -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 3588721849..a1d5db2e27 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -48,7 +48,6 @@ LLTipHandler::LLTipHandler()  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->addOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -127,22 +126,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)  	p.is_tip = true;  	p.can_be_stored = false; -	removeExclusiveNotifications(notification); -  	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get());  	if(channel)  		channel->addToast(p);  	return false;  } - -//-------------------------------------------------------------------------- - -void LLTipHandler::onRejectToast(const LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification && mItems.find(notification) != mItems.end()) -	{ -		LLNotifications::instance().cancel(notification); -	} -} diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 003b53b28c..839ca0f9c5 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -265,7 +265,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  	if(!show_toast && !store_toast)  	{ -		mRejectToastSignal(p.notif_id); +		LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id); + +		if (notification && +			(!notification->canLogToIM() || !notification->hasFormElements())) +		{ +			// only cancel notification if it isn't being used in IM session +			LLNotifications::instance().cancel(notification); +		}  		return;  	} @@ -432,34 +439,12 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  }  //-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) -{ -	// *TODO: may be remove this function -	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if( it == mStoredToastList.end() ) -		return; - -	const LLToast* toast = it->getToast(); -	if (toast) -	{ -		mRejectToastSignal(toast->getNotificationID()); -	} - -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid. -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); -	if (it != mStoredToastList.end()) -	{ -	mStoredToastList.erase(it); -	} -} - -//--------------------------------------------------------------------------  void LLScreenChannel::killToastByNotificationID(LLUUID id)  {  	// searching among toasts on a screen  	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (!notification) return;  	if( it != mToastList.end())  	{ @@ -472,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  		//			the toast will be destroyed.  		if(toast && toast->isNotificationValid())  		{ -			mRejectToastSignal(toast->getNotificationID()); +			if (!notification->canLogToIM() || !notification->hasFormElements()) +			{ +				// only cancel notification if it isn't being used in IM session +				LLNotifications::instance().cancel(notification); +			}  		}  		else  		{ - -			deleteToast(toast); -			mToastList.erase(it); -			redrawToasts(); +			removeToastByNotificationID(id);  		} -		return;  	} - -	// searching among stored toasts -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if( it != mStoredToastList.end() ) +	else  	{ -		LLToast* toast = it->getToast(); -		if (toast) +		// searching among stored toasts +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + +		if( it != mStoredToastList.end() ) +		{ +			LLToast* toast = it->getToast(); +			if (toast) +			{ +				if (!notification->canLogToIM() || !notification->hasFormElements()) +				{ +					// only cancel notification if it isn't being used in IM session +					LLNotifications::instance().cancel(notification); +				} +				deleteToast(toast); +			} +		} +	 +		// Call find() once more, because the mStoredToastList could have been changed +		// via notification cancellation and the iterator could have become invalid. +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +		if (it != mStoredToastList.end())  		{ -		// send signal to a listener to let him perform some action on toast rejecting -		mRejectToastSignal(toast->getNotificationID()); -		deleteToast(toast); +			mStoredToastList.erase(it); +		}  	}  } -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid. -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); -	if (it != mStoredToastList.end()) +void LLScreenChannel::removeToastByNotificationID(LLUUID id) +{ +	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	if( it != mToastList.end())  	{ -		mStoredToastList.erase(it); +		deleteToast(it->getToast()); +		mToastList.erase(it); +		redrawToasts(); +	} +	else +	{ +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +		if (it != mStoredToastList.end()) +		{ +			deleteToast(it->getToast()); +			mStoredToastList.erase(it); +		}  	} -  } +  void LLScreenChannel::killMatchedToasts(const Matcher& matcher)  {  	std::list<const LLToast*> to_delete = findToasts(matcher); diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index eaff61a0f4..e5f4807ab7 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -84,6 +84,7 @@ public:  	// kill or modify a toast by its ID  	virtual void		killToastByNotificationID(LLUUID id) {};  	virtual void		modifyToastNotificationByID(LLUUID id, LLSD data) {}; +	virtual void		removeToastByNotificationID(LLUUID id){};  	// hide all toasts from screen, but not remove them from a channel  	virtual void		hideToastsFromScreen() {}; @@ -175,6 +176,7 @@ public:  	void		addToast(const LLToast::Params& p);  	// kill or modify a toast by its ID  	void		killToastByNotificationID(LLUUID id); +	void		removeToastByNotificationID(LLUUID id);  	void		killMatchedToasts(const Matcher& matcher);  	void		modifyToastByNotificationID(LLUUID id, LLPanel* panel);  	// hide all toasts from screen, but not remove them from a channel @@ -195,8 +197,6 @@ public:  	void		loadStoredToastsToChannel();  	// finds a toast among stored by its Notification ID and throws it on a screen to a channel  	void		loadStoredToastByNotificationIDToChannel(LLUUID id); -	// removes a toast from stored finding it by its Notification ID  -	void		removeStoredToastByNotificationID(LLUUID id);  	// removes from channel all toasts that belongs to the certain IM session   	void		removeToastsBySessionID(LLUUID id);  	// remove all storable toasts from screen and store them @@ -229,13 +229,9 @@ public:  	// signal on storing of faded toasts event  	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t;  	boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); } -	// signal on rejecting of a toast event -	typedef boost::signals2::signal<void (LLUUID id)> reject_toast_signal_t; -	boost::signals2::connection addOnRejectToastCallback(reject_toast_signal_t::slot_type cb) { return mRejectToastSignal.connect(cb); }  private:  	store_toast_signal_t mOnStoreToast;	 -	reject_toast_signal_t mRejectToastSignal;   	class ToastElem  	{ diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..ea62f758f8 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -169,6 +169,7 @@ public:  	// get/set Toast's flags or states  	// get information whether the notification corresponding to the toast is valid or not  	bool isNotificationValid(); +  	// get toast's Notification ID  	const LLUUID getNotificationID() const { return mNotificationID;}  	// get toast's Session ID @@ -212,7 +213,7 @@ private:  	//LLRootHandle<LLToast>	mHandle; -	LLPanel* mWrapperPanel; +	LLPanel*	 mWrapperPanel;  	// timer counts a lifetime of a toast  	std::auto_ptr<LLToastLifeTimer> mTimer; @@ -220,8 +221,8 @@ private:  	F32			mToastLifetime; // in seconds  	F32			mToastFadingTime; // in seconds -	LLPanel*		mPanel; -	LLButton*		mHideBtn; +	LLPanel*	mPanel; +	LLButton*	mHideBtn;  	LLColor4	mBgColor;  	bool		mCanFade; diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index a803387576..279dd69bc7 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -41,11 +41,11 @@ public:  	struct Params  	{  		LLNotificationPtr	notification; -		LLUUID				avatar_id; -		LLUUID				session_id; -		std::string			from; -		std::string			time; -		std::string			message; +		LLUUID				avatar_id, +							session_id; +		std::string			from, +							time, +							message;  		Params() {}  	}; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index dc5cc88dc4..77a5a5d17d 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,9 @@  const S32 BOTTOM_PAD = VPAD * 3;  const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding  S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  +  //static  const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -52,171 +55,24 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;  LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) :  -LLToastPanel(notification), -mTextBox(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false), -mCloseNotificationOnDestroy(true) +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)  +:	LLToastPanel(notification), +	LLInstanceTracker(notification->getID())  { -	buildFromFile( "panel_notification.xml"); -	if(rect != LLRect::null) -	{ -		this->setShape(rect); -	}		  -	mInfoPanel = getChild<LLPanel>("info_panel"); -	mControlPanel = getChild<LLPanel>("control_panel"); -	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); -	// customize panel's attributes -	// is it intended for displaying a tip? -	mIsTip = notification->getType() == "notifytip"; -	// is it a script dialog? -	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); -	// is it a caution? -	// -	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the -	// notify xml template specifies that it is a caution -	// tip-style notification handle 'caution' differently -they display the tip in a different color -	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; +	init(rect, show_images); -	// setup parameters -	// get a notification message -	mMessage = notification->getMessage(); -	// init font variables -	if (!sFont) -	{ -		sFont = LLFontGL::getFontSansSerif(); -		sFontSmall = LLFontGL::getFontSansSerifSmall(); -	} -	// initialize -	setFocusRoot(!mIsTip); -	// get a form for the notification -	LLNotificationFormPtr form(notification->getForm()); -	// get number of elements -	mNumOptions = form->getNumElements(); -	// customize panel's outfit -	// preliminary adjust panel's layout -	//move to the end  -	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - -	// adjust text options according to the notification type -	// add a caution textbox at the top of a caution notification -	if (mIsCaution && !mIsTip) -	{ -		mTextBox = getChild<LLTextBox>("caution_text_box"); -	} -	else -	{ -		mTextBox = getChild<LLTextEditor>("text_editor_box");  -	} - -	// *TODO: magic numbers(???) - copied from llnotify.cpp(250) -	const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  - -	mTextBox->setMaxTextLength(MAX_LENGTH); -	mTextBox->setVisible(TRUE); -	mTextBox->setPlainText(!show_images); -	mTextBox->setValue(notification->getMessage()); - -	// add buttons for a script notification -	if (mIsTip) -	{ -		adjustPanelForTipNotice(); -	} -	else -	{ -		std::vector<index_button_pair_t> buttons; -		buttons.reserve(mNumOptions); -		S32 buttons_width = 0; -		// create all buttons and accumulate they total width to reshape mControlPanel -		for (S32 i = 0; i < mNumOptions; i++) -		{ -			LLSD form_element = form->getElement(i); -			if (form_element["type"].asString() != "button") -			{ -				// not a button. -				continue; -			} -			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) -			{ -				// a textbox pretending to be a button. -				continue; -			} -			LLButton* new_button = createButton(form_element, TRUE); -			buttons_width += new_button->getRect().getWidth(); -			S32 index = form_element["index"].asInteger(); -			buttons.push_back(index_button_pair_t(index,new_button)); -		} -		if (buttons.empty()) -		{ -			addDefaultButton(); -		} -		else -		{ -			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel -			S32 button_panel_height = mControlPanel->getRect().getHeight(); -			//try get an average h_pad to spread out buttons -			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); -			if(h_pad < 2*HPAD) -			{ -				/* -				 * Probably it is a scriptdialog toast -				 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. -				 * In last case set default h_pad to avoid heaping of buttons  -				 */ -				S32 button_per_row = button_panel_width / BUTTON_WIDTH; -				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    -				if(h_pad < 2*HPAD) // still not enough space between buttons ? -				{ -					h_pad = 2*HPAD; -				} -			} -			if (mIsScriptDialog) -			{ -				// we are using default width for script buttons so we can determinate button_rows -				//to get a number of rows we divide the required width of the buttons to button_panel_width -				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); -				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; -				//reserve one row for the ignore_btn -				button_rows++; -				//calculate required panel height for scripdialog notification. -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; -			} -			else -			{ -				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width -				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); -				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); -				//calculate required panel height  -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD; -			} -		 -			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed -			adjustPanelForScriptNotice(button_panel_width, button_panel_height); -			updateButtonsLayout(buttons, h_pad); -			// save buttons for later use in disableButtons() -			mButtons.assign(buttons.begin(), buttons.end()); -		} -	} -	// adjust panel's height to the text size -	mInfoPanel->setFollowsAll(); -	snapToMessageHeight(mTextBox, MAX_LENGTH); - -	if(notification->isReusable()) -	{ -		mButtonClickConnection = sButtonClickSignal.connect( -			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); - -		if(notification->isRespondedTo()) -		{ -			// User selected an option in toast, now disable required buttons in IM window -			disableRespondedOptions(notification); -		} -	} +	//if(notification->isRespondedTo()) +	//{ +	//	// User selected an option in toast, now disable required buttons in IM window +	//	disableRespondedOptions(notification); +	//} +	// +	//if(notification->isReusable()) +	//{ +	//	mButtonClickConnection = sButtonClickSignal.connect( +	//		boost::bind(&LLToastNotifyPanel::disableRespondedOptions, this, notification)); +	//}  }  void LLToastNotifyPanel::addDefaultButton()  { @@ -235,7 +91,6 @@ void LLToastNotifyPanel::addDefaultButton()  }  LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option)  { -  	InstanceAndS32* userdata = new InstanceAndS32;  	userdata->mSelf = this;  	userdata->mButtonName = is_option ? form_element["name"].asString() : ""; @@ -245,14 +100,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt  	LLButton::Params p;  	bool is_ignore_btn = form_element["index"].asInteger() == -1;  	const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button in script dialog -	p.name(form_element["name"].asString()); -	p.label(form_element["text"].asString()); -	p.font(font); +	p.name = form_element["name"].asString(); +	p.label = form_element["text"].asString(); +	p.font = font;  	p.rect.height = BTN_HEIGHT;  	p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));  	p.rect.width = BUTTON_WIDTH;  	p.auto_resize = false;  	p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); +	p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean();  	if (mIsCaution)  	{  		p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); @@ -287,14 +143,9 @@ LLToastNotifyPanel::~LLToastNotifyPanel()  	mButtonClickConnection.disconnect();  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL) +	if (mIsTip)  	{ -		// let reusable notification be deleted -		mNotification->setReusable(false); -		if (!mNotification->isPersistent()) -		{ -			LLNotifications::getInstance()->cancel(mNotification); -		} +		LLNotifications::getInstance()->cancel(mNotification);  	}  } @@ -393,103 +244,103 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()  	}  } -typedef std::set<std::string> button_name_set_t; -typedef std::map<std::string, button_name_set_t> disable_button_map_t; - -disable_button_map_t initUserGiveItemDisableButtonMap() -{ -	// see EXT-5905 for disable rules - -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Show"); -	disable_map.insert(std::make_pair("Show", buttons)); - -	buttons.insert("Discard"); -	disable_map.insert(std::make_pair("Discard", buttons)); - -	buttons.insert("Mute"); -	disable_map.insert(std::make_pair("Mute", buttons)); - -	return disable_map; -} - -disable_button_map_t initTeleportOfferedDisableButtonMap() -{ -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Teleport"); -	buttons.insert("Cancel"); - -	disable_map.insert(std::make_pair("Teleport", buttons)); -	disable_map.insert(std::make_pair("Cancel", buttons)); - -	return disable_map; -} - -disable_button_map_t initFriendshipOfferedDisableButtonMap() -{ -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Accept"); -	buttons.insert("Decline"); - -	disable_map.insert(std::make_pair("Accept", buttons)); -	disable_map.insert(std::make_pair("Decline", buttons)); - -	return disable_map; -} - -button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -{ -	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); -	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); -	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); - -	disable_button_map_t::const_iterator it; -	disable_button_map_t::const_iterator it_end; -	disable_button_map_t search_map; - -	if("UserGiveItem" == notification_name) -	{ -		search_map = user_give_item_disable_map; -	} -	else if("TeleportOffered" == notification_name) -	{ -		search_map = teleport_offered_disable_map; -	} -	else if("OfferFriendship" == notification_name) -	{ -		search_map = friendship_offered_disable_map; -	} - -	it = search_map.find(button_name); -	it_end = search_map.end(); - -	if(it_end != it) -	{ -		return it->second; -	} -	return button_name_set_t(); -} - -void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) -{ -	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - -	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); -	for ( ; it != mButtons.end(); it++) -	{ -		LLButton* btn = it->second; -		if(buttons.find(btn->getName()) != buttons.end()) -		{ -			btn->setEnabled(FALSE); -		} -	} -} +//typedef std::set<std::string> button_name_set_t; +//typedef std::map<std::string, button_name_set_t> disable_button_map_t; +// +//disable_button_map_t initUserGiveItemDisableButtonMap() +//{ +//	// see EXT-5905 for disable rules +// +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Show"); +//	disable_map.insert(std::make_pair("Show", buttons)); +// +//	buttons.insert("Discard"); +//	disable_map.insert(std::make_pair("Discard", buttons)); +// +//	buttons.insert("Mute"); +//	disable_map.insert(std::make_pair("Mute", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initTeleportOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Teleport"); +//	buttons.insert("Cancel"); +// +//	disable_map.insert(std::make_pair("Teleport", buttons)); +//	disable_map.insert(std::make_pair("Cancel", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initFriendshipOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Accept"); +//	buttons.insert("Decline"); +// +//	disable_map.insert(std::make_pair("Accept", buttons)); +//	disable_map.insert(std::make_pair("Decline", buttons)); +// +//	return disable_map; +//} +// +//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +//{ +//	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +//	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +//	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); +// +//	disable_button_map_t::const_iterator it; +//	disable_button_map_t::const_iterator it_end; +//	disable_button_map_t search_map; +// +//	if("UserGiveItem" == notification_name) +//	{ +//		search_map = user_give_item_disable_map; +//	} +//	else if("TeleportOffered" == notification_name) +//	{ +//		search_map = teleport_offered_disable_map; +//	} +//	else if("OfferFriendship" == notification_name) +//	{ +//		search_map = friendship_offered_disable_map; +//	} +// +//	it = search_map.find(button_name); +//	it_end = search_map.end(); +// +//	if(it_end != it) +//	{ +//		return it->second; +//	} +//	return button_name_set_t(); +//} + +//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +//{ +	//button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + +	//std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); +	//for ( ; it != mButtons.end(); it++) +	//{ +	//	LLButton* btn = it->second; +	//	if(buttons.find(btn->getName()) != buttons.end()) +	//	{ +	//		btn->setEnabled(FALSE); +	//	} +	//} +//}  // static  void LLToastNotifyPanel::onClickButton(void* data) @@ -515,88 +366,263 @@ void LLToastNotifyPanel::onClickButton(void* data)  		self->mNotification->setResponder(new_info);  	} +	// disable all buttons +	self->mControlPanel->setEnabled(FALSE); + +	// this might repost notification with new form data/enabled buttons  	self->mNotification->respond(response); +} -	if(is_reusable) +void LLToastNotifyPanel::init( LLRect rect, bool show_images ) +{ +	deleteAllChildren(); + +	mTextBox = NULL; +	mInfoPanel = NULL; +	mControlPanel = NULL; +	mNumOptions = 0; +	mNumButtons = 0; +	mAddedDefaultBtn = false; + +	buildFromFile( "panel_notification.xml"); +	if(rect != LLRect::null)  	{ -		sButtonClickSignal(self->mNotification->getID(), button_name); +		this->setShape(rect); +	}		  +	mInfoPanel = getChild<LLPanel>("info_panel"); +	mInfoPanel->setFollowsAll(); + +	mControlPanel = getChild<LLPanel>("control_panel"); +	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); +	// customize panel's attributes +	// is it intended for displaying a tip? +	mIsTip = mNotification->getType() == "notifytip"; +	// is it a script dialog? +	mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); +	// is it a caution? +	// +	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the +	// notify xml template specifies that it is a caution +	// tip-style notification handle 'caution' differently -they display the tip in a different color +	mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + +	// setup parameters +	// get a notification message +	mMessage = mNotification->getMessage(); +	// init font variables +	if (!sFont) +	{ +		sFont = LLFontGL::getFontSansSerif(); +		sFontSmall = LLFontGL::getFontSansSerifSmall(); +	} +	// initialize +	setFocusRoot(!mIsTip); +	// get a form for the notification +	LLNotificationFormPtr form(mNotification->getForm()); +	// get number of elements +	mNumOptions = form->getNumElements(); + +	// customize panel's outfit +	// preliminary adjust panel's layout +	//move to the end  +	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + +	// adjust text options according to the notification type +	// add a caution textbox at the top of a caution notification +	if (mIsCaution && !mIsTip) +	{ +		mTextBox = getChild<LLTextBox>("caution_text_box");  	}  	else  	{ -		// disable all buttons -		self->mControlPanel->setEnabled(FALSE); +		mTextBox = getChild<LLTextEditor>("text_editor_box");   	} -} -void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) -{ -	if(mNotification->getID() == notification_id) +	mTextBox->setMaxTextLength(MAX_LENGTH); +	mTextBox->setVisible(TRUE); +	mTextBox->setPlainText(!show_images); +	mTextBox->setValue(mNotification->getMessage()); + +	// add buttons for a script notification +	if (mIsTip)  	{ -		disableButtons(mNotification->getName(), btn_name); +		adjustPanelForTipNotice();  	} -} - -void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) -{ -	LLSD response = notification->getResponse(); -	for (LLSD::map_const_iterator response_it = response.beginMap();  -		response_it != response.endMap(); ++response_it) +	else  	{ -		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +		std::vector<index_button_pair_t> buttons; +		buttons.reserve(mNumOptions); +		S32 buttons_width = 0; +		// create all buttons and accumulate they total width to reshape mControlPanel +		for (S32 i = 0; i < mNumOptions; i++)  		{ -			// that after multiple responses there can be many pressed buttons -			// need to process them all -			disableButtons(notification->getName(), response_it->first); +			LLSD form_element = form->getElement(i); +			if (form_element["type"].asString() != "button") +			{ +				// not a button. +				continue; +			} +			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) +			{ +				// a textbox pretending to be a button. +				continue; +			} +			LLButton* new_button = createButton(form_element, TRUE); +			buttons_width += new_button->getRect().getWidth(); +			S32 index = form_element["index"].asInteger(); +			buttons.push_back(index_button_pair_t(index,new_button)); +		} +		if (buttons.empty()) +		{ +			addDefaultButton(); +		} +		else +		{ +			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel +			S32 button_panel_height = mControlPanel->getRect().getHeight(); +			//try get an average h_pad to spread out buttons +			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); +			if(h_pad < 2*HPAD) +			{ +				/* +				* Probably it is a scriptdialog toast +				* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. +				* In last case set default h_pad to avoid heaping of buttons  +				*/ +				S32 button_per_row = button_panel_width / BUTTON_WIDTH; +				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    +				if(h_pad < 2*HPAD) // still not enough space between buttons ? +				{ +					h_pad = 2*HPAD; +				} +			} +			if (mIsScriptDialog) +			{ +				// we are using default width for script buttons so we can determinate button_rows +				//to get a number of rows we divide the required width of the buttons to button_panel_width +				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); +				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; +				//reserve one row for the ignore_btn +				button_rows++; +				//calculate required panel height for scripdialog notification. +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; +			} +			else +			{ +				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width +				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); +				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); +				//calculate required panel height  +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD; +			} + +			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed +			adjustPanelForScriptNotice(button_panel_width, button_panel_height); +			updateButtonsLayout(buttons, h_pad); +			// save buttons for later use in disableButtons() +			//mButtons.assign(buttons.begin(), buttons.end());  		}  	} +	// adjust panel's height to the text size +	snapToMessageHeight(mTextBox, MAX_LENGTH);  } + +//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +//{ +//	if(mNotification->getID() == notification_id) +//	{ +//		disableButtons(mNotification->getName(), btn_name); +//	} +//} + +//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) +//{ +//	LLSD response = notification->getResponse(); +//	for (LLSD::map_const_iterator response_it = response.beginMap();  +//		response_it != response.endMap(); ++response_it) +//	{ +//		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +//		{ +//			// that after multiple responses there can be many pressed buttons +//			// need to process them all +//			disableButtons(notification->getName(), response_it->first); +//		} +//	} +//} + +  //////////////////////////////////////////////////////////////////////////  LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, -										   bool show_images /* = true */) - : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images) +										   bool show_images /* = true */, LLTextBase* parent_text) +:	mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), +	mParentText(parent_text)  { -	mTextBox->setFollowsAll(); +	compactButtons();  }  LLIMToastNotifyPanel::~LLIMToastNotifyPanel()  { -	// We shouldn't delete notification when IM floater exists -	// since that notification will be reused by IM floater. -	// This may happened when IM floater reloads messages, exactly when user -	// changes layout of IM chat log(disable/enable plaintext mode). -	// See EXT-6500 -	LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); -	if (im_floater != NULL && !im_floater->isDead()) -	{ -		mCloseNotificationOnDestroy = false; -	}  }  void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)  { -	S32 text_height = mTextBox->getTextBoundingRect().getHeight(); -	S32 widget_height = mTextBox->getRect().getHeight(); -	S32 delta = text_height - widget_height; -	LLRect rc = getRect(); +	LLToastPanel::reshape(width, height, called_from_parent); -	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); -	height = rc.getHeight(); -	width = rc.getWidth(); +	snapToMessageHeight(mTextBox, MAX_LENGTH); +} -	bool is_width_changed = width != getRect().getWidth(); +void LLIMToastNotifyPanel::compactButtons() +{ +	mTextBox->setFollowsAll(); -	LLToastPanel::reshape(width, height, called_from_parent); +	//we can't set follows in xml since it broke toasts behavior +	setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); -	// Notification height required to display the text message depends on -	// the width of the text box thus if panel width is changed the text box -	// width is also changed then reshape() is called to adjust proper height. -	if (is_width_changed) +	const child_list_t* children = getControlPanel()->getChildList(); +	S32 offset = 0; +	// Children were added by addChild() which uses push_front to insert them into list, +	// so to get buttons in correct order reverse iterator is used (EXT-5906)  +	for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++)  	{ -		reshape(width, height, called_from_parent); +		LLButton * button = dynamic_cast<LLButton*> (*it); +		if (button != NULL) +		{ +			button->setOrigin( offset,button->getRect().mBottom); +			button->setLeftHPad(2 * HPAD); +			button->setRightHPad(2 * HPAD); +			// set zero width before perform autoResize() +			button->setRect(LLRect(button->getRect().mLeft, +				button->getRect().mTop,  +				button->getRect().mLeft, +				button->getRect().mBottom)); +			button->setAutoResize(true); +			button->autoResize(); +			offset += HPAD + button->getRect().getWidth(); +			button->setFollowsNone(); +		}  	} + +	if (mParentText) +	{ +		mParentText->needsReflow(); +	} +} + +void LLIMToastNotifyPanel::updateNotification() +{ +	init(LLRect(), true); +} + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ +	LLToastNotifyPanel::init(LLRect(), show_images); + +	compactButtons();  } +  // EOF + diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index db517ec858..f93c7745af 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm;   * @deprecated this class will be removed after all toast panel types are   *  implemented in separate classes.   */ -class LLToastNotifyPanel: public LLToastPanel  +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID>  {  public:  	/** @@ -61,10 +61,14 @@ public:  	 * implement right class for desired toast panel. @see LLGenericTipPanel as example.  	 */  	LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + +	virtual void init( LLRect rect, bool show_images ); +  	virtual ~LLToastNotifyPanel();  	LLPanel * getControlPanel() { return mControlPanel; } -	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; } +	virtual void updateNotification() {} +  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,8 +80,6 @@ protected:  	};  	std::vector<InstanceAndS32*> mBtnCallbackData; -	bool mCloseNotificationOnDestroy; -  	typedef std::pair<int,LLButton*> index_button_pair_t;   	void adjustPanelForScriptNotice(S32 max_width, S32 max_height);  	void adjustPanelForTipNotice(); @@ -93,9 +95,9 @@ protected:  	/**  	 * Disable specific button(s) based on notification name and clicked button  	 */ -	void disableButtons(const std::string& notification_name, const std::string& selected_button); +	//void disableButtons(const std::string& notification_name, const std::string& selected_button); -	std::vector<index_button_pair_t> mButtons; +	//std::vector<index_button_pair_t> mButtons;  	// panel elements  	LLTextBase*		mTextBox; @@ -118,7 +120,7 @@ protected:  	/**  	 * Process response data. Will disable selected options  	 */ -	void disableRespondedOptions(const LLNotificationPtr& notification); +	//void disableRespondedOptions(const LLNotificationPtr& notification);  	bool mIsTip;  	bool mAddedDefaultBtn; @@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel  {  public: -	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true); +	LLIMToastNotifyPanel(LLNotificationPtr& pNotification,  +						const LLUUID& session_id,  +						const LLRect& rect = LLRect::null,  +						bool show_images = true,  +						LLTextBase* parent_text = NULL); + +	void compactButtons(); + +	virtual void updateNotification(); +	virtual void init( LLRect rect, bool show_images );  	~LLIMToastNotifyPanel();  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  protected: +	LLTextBase* mParentText;  	LLUUID	mSessionID;  }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index d2a4ce8745..e20d516392 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -78,11 +78,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  		S32 requiredTextHeight = message->getTextBoundingRect().getHeight();  		S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); -		//Calculate last delta height deducting previous heightDelta  -		heightDelta = newTextHeight - oldTextHeight - heightDelta; +		heightDelta = newTextHeight - oldTextHeight; +		S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT);  		//reshape the panel with new height -		reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); +		if (new_panel_height != getRect().getHeight()) +		{ +			reshape( getRect().getWidth(), new_panel_height); +		}  	}  } @@ -96,7 +99,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(  	if ("notifytip" == notification->getType())  	{  		// if it is online/offline notification -		if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) +		if ("FriendOnlineOffline" == notification->getName())  		{  			res = new LLPanelOnlineStatus(notification);  		} diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 346e014d73..c22557206b 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -33,19 +33,13 @@  #include <string> -class LLToastPanelBase: public LLPanel  -{ -public: -	virtual void init(LLSD& data){}; -}; -  /**   * Base class for all panels that can be added to the toast.   * All toast panels should contain necessary logic for representing certain notification   * but shouldn't contain logic related to this panel lifetime control and positioning   * on the parent view.   */ -class LLToastPanel: public LLPanel { +class LLToastPanel : public LLPanel {  public:  	LLToastPanel(const LLNotificationPtr&);  	virtual ~LLToastPanel() = 0; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c2bafd043d..cefd9ef91d 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,6 +179,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	LLMessageSystem* msg = gMessageSystem;  	const LLSD& payload = notification["payload"]; +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());  	// add friend to recent people list  	LLRecentPeople::instance().add(payload["from_id"]); @@ -204,7 +205,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		msg->sendReliable(LLHost(payload["sender"].asString()));  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipAcceptedByMe",  				notification["substitutions"], payload);  		break; @@ -212,7 +212,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	case 1: // Decline  	{  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipDeclinedByMe",  				notification["substitutions"], payload);  	} @@ -241,6 +240,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		break;  	} +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Accept", false); +	modified_form->setElementEnabled("Decline", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); @@ -1471,16 +1476,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);  	} +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); +	llassert(notification_ptr != NULL); +	  	// For muting, we need to add the mute, then decline the offer.  	// This must be done here because:  	// * callback may be called immediately,  	// * adding the mute sends a message,  	// * we can't build two messages at once. -	if (2 == button) // Block +	if (IOR_MUTE == button) // Block  	{ -		LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - -		llassert(notification_ptr != NULL);  		if (notification_ptr != NULL)  		{  			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); @@ -1495,6 +1500,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	bool busy = gAgent.getBusy(); +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +  	switch(button)  	{  	case IOR_SHOW: @@ -1538,6 +1545,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break;  		} + +		modified_form->setElementEnabled("Show", false);  		break;  		// end switch (mIM) @@ -1550,9 +1559,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			args["MESSAGE"] = log_message;  			LLNotificationsUtil::add("SystemMessageTip", args);  		} +  		break;  	case IOR_MUTE: +		modified_form->setElementEnabled("Mute", false);  		// MUTE falls through to decline  	case IOR_DECLINE:  		{ @@ -1588,6 +1599,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			{  				busy_message(gMessageSystem, mFromID);  			} + +			modified_form->setElementEnabled("Show", false); +			modified_form->setElementEnabled("Discard", false); +  			break;  		}  	default: @@ -1607,6 +1622,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	{  		delete this;  	} + +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  } @@ -1984,6 +2003,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response)  					   lure_id);  		break;  	} + +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Teleport", false); +	modified_form->setElementEnabled("Cancel", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); @@ -6394,7 +6422,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  				//*TODO please rewrite all keys to the same case, lower or upper  				payload["from_id"] = target_id; -				payload["SUPPRESS_TOAST"] = true;  				LLNotificationsUtil::add("TeleportOfferSent", args, payload);  				// Add the recepient to the recent people list. diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d35cebbd16..5b7222c180 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5208,20 +5208,14 @@ Topic: [SUBJECT], Message: [MESSAGE]    <notification     icon="notifytip.tga" -   name="FriendOnline" +   name="FriendOnlineOffline"     log_to_chat="false"     type="notifytip">      <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online -  </notification> - -  <notification -   icon="notifytip.tga" -   name="FriendOffline" -   log_to_chat="false" -   type="notifytip"> -    <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +<nolink>[NAME]</nolink> is [STATUS] +    <unique combine="cancel_old"> +      <context>NAME</context> +    </unique>    </notification>    <notification @@ -6160,7 +6154,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOfferSent" -   log_to_im="true"    +   log_to_im="true" +   show_toast="false"     type="offer">  	Teleport offer sent to [TO_NAME]    </notification> @@ -6213,6 +6208,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th     icon="notify.tga"     name="FriendshipOffered"     log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  	You have offered friendship to [TO_NAME] @@ -6262,6 +6258,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th     icon="notify.tga"     name="FriendshipAcceptedByMe"     log_to_im="true"    +   show_toast="false"     type="offer">      <tag>friendship</tag>  Friendship offer accepted. @@ -6271,6 +6268,7 @@ Friendship offer accepted.     icon="notify.tga"     name="FriendshipDeclinedByMe"     log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  Friendship offer declined. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9752652679..e932310622 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3242,6 +3242,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="IM_moderator_label">(Moderator)</string>  	<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string>  	<string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> +  <string name="OnlineStatus">Online</string> +  <string name="OfflineStatus">Offline</string>  	<!-- voice calls -->  	<string name="answered_call">Your call has been answered</string>  | 
