From 9f0dbcf4c0c6c8621c377fd7f9e417aa76acd836 Mon Sep 17 00:00:00 2001
From: Dmitry Zaporozhan <dzaporozhan@productengine.com>
Date: Mon, 23 Nov 2009 15:50:49 +0200
Subject: Update for task EXT-2081 - Object IM chiclets art needs to be hooked
 up to LLDialog chiclets. Cleaned code, added comments.

--HG--
branch : product-engine
---
 indra/newview/llchiclet.cpp                        | 30 +++-----
 indra/newview/llchiclet.h                          | 26 ++++---
 indra/newview/llnotificationscripthandler.cpp      | 16 ++--
 indra/newview/llscriptfloater.cpp                  | 88 +++++++++++-----------
 indra/newview/llscriptfloater.h                    | 66 ++++++++++++++--
 indra/newview/llviewermessage.cpp                  |  4 +-
 .../newview/skins/default/xui/en/notifications.xml |  4 +-
 .../default/xui/en/widgets/chiclet_script.xml      |  9 +++
 8 files changed, 155 insertions(+), 88 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_script.xml

diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index fd91da2de2..433f70700c 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -56,6 +56,7 @@ static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notif
 static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p");
 static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group");
 static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");
+static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");
 
 static const LLRect CHICLET_RECT(0, 25, 25, 0);
 static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0);
@@ -1418,24 +1419,21 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)
 //////////////////////////////////////////////////////////////////////////
 
 LLScriptChiclet::Params::Params()
- : avatar_icon("avatar_icon")
+ : icon("icon")
 {
 	// *TODO Vadim: Get rid of hardcoded values.
-	rect(CHICLET_RECT);
-	name("dialog_chiclet");
-
-	avatar_icon.name("avatar_icon");
-	avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
-
-	avatar_icon.rect(CHICLET_ICON_RECT);
-	avatar_icon.mouse_opaque(false);
+ 	rect(CHICLET_RECT);
+	icon.rect(CHICLET_ICON_RECT);
 }
 
 LLScriptChiclet::LLScriptChiclet(const Params&p)
  : LLIMChiclet(p)
  , mChicletIconCtrl(NULL)
 {
-	mImage = LLUI::getUIImage("Generic_Object_Small");
+	LLIconCtrl::Params icon_params = p.icon;
+	mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
+	// Let "new message" icon be on top, else it will be hidden behind chiclet icon.
+	addChildInBack(mChicletIconCtrl);
 }
 
 void LLScriptChiclet::setSessionId(const LLUUID& session_id)
@@ -1443,20 +1441,14 @@ void LLScriptChiclet::setSessionId(const LLUUID& session_id)
 	setShowNewMessagesIcon( getSessionId() != session_id );
 
 	LLIMChiclet::setSessionId(session_id);
-	LLNotificationPtr notification = LLNotifications::getInstance()->find(
-		LLScriptFloaterManager::getInstance()->getNotificationId(session_id));
+	LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(session_id);
+	LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
 	if(notification)
 	{
 		setToolTip(notification->getSubstitutions()["TITLE"].asString());
 	}
 }
 
-void LLScriptChiclet::draw()
-{
-	mImage->draw(getLocalRect());
-	LLIMChiclet::draw();
-}
-
 void LLScriptChiclet::onMouseDown()
 {
 	LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId());
@@ -1467,3 +1459,5 @@ BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
 	onMouseDown();
 	return LLChiclet::handleMouseDown(x, y, mask);
 }
+
+// EOF
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index 56f164738e..1ea141e6c4 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -533,28 +533,35 @@ private:
 	LLMenuGL* mPopupMenu;
 };
 
+/**
+ * Chiclet for script floaters.
+ */
 class LLScriptChiclet : public LLIMChiclet
 {
 public:
 
 	struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
 	{
-		Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
+		Optional<LLIconCtrl::Params> icon;
 
 		Params();
 	};
 
-	void setSessionId(const LLUUID& session_id);
-
-	void setCounter(S32 counter){}
+	/*virtual*/ void setSessionId(const LLUUID& session_id);
 
-	S32 getCounter() { return 0; }
+	/*virtual*/ void setCounter(S32 counter){}
 
-	void onMouseDown();
+	/*virtual*/ S32 getCounter() { return 0; }
 
-	BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+	/**
+	 * Toggle script floater
+	 */
+	/*virtual*/ void onMouseDown();
 
-	void draw();
+	/**
+	 * Override default handler
+	 */
+	/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
 
 protected:
 
@@ -563,8 +570,7 @@ protected:
 
 private:
 
-	LLPointer<LLUIImage> mImage;
-	LLChicletAvatarIconCtrl* mChicletIconCtrl;
+	LLIconCtrl* mChicletIconCtrl;
 };
 
 /**
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 2cac86cc0b..f01f2e4441 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -42,6 +42,9 @@
 
 using namespace LLNotificationsUI;
 
+static const std::string SCRIPT_DIALOG				("ScriptDialog");
+static const std::string SCRIPT_DIALOG_GROUP		("ScriptDialogGroup");
+
 //--------------------------------------------------------------------------
 LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id)
 {
@@ -91,7 +94,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify)
 	
 	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
 	{
-		if("ScriptDialog" == notification->getName() || "ScriptDialogGroup" == notification->getName())
+		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName())
 		{
 			LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());
 		}
@@ -117,11 +120,14 @@ bool LLScriptHandler::processNotification(const LLSD& notify)
 	}
 	else if (notify["sigtype"].asString() == "delete")
 	{
-		mChannel->killToastByNotificationID(notification->getID());
-		if("ScriptDialog" == notification->getName())
+		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName())
 		{
 			LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());
 		}
+		else
+		{
+			mChannel->killToastByNotificationID(notification->getID());
+		}
 	}
 	return true;
 }
@@ -139,8 +145,8 @@ void LLScriptHandler::onDeleteToast(LLToast* toast)
 
 	LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID());
 	
-	if( notification && ("ScriptDialog" == notification->getName() 
-		|| "ScriptDialogGroup" == notification->getName()) )
+	if( notification && 
+		(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) )
 	{
 		LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());
 	}
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 1bf6235d04..bdea6ff459 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -61,6 +61,7 @@ LLUUID notification_id_to_object_id(const LLUUID& notification_id)
 
 LLScriptFloater::LLScriptFloater(const LLSD& key)
 : LLTransientDockableFloater(NULL, true, key)
+, mScriptForm(NULL)
 , mObjectId(key.asUUID())
 {
 }
@@ -84,6 +85,7 @@ bool LLScriptFloater::toggle(const LLUUID& object_id)
 			return true;
 		}
 	}
+	// create and show new floater
 	else
 	{
 		show(object_id);
@@ -122,58 +124,54 @@ void LLScriptFloater::getAllowedRect(LLRect& rect)
 
 void LLScriptFloater::createForm(const LLUUID& object_id)
 {
-	static const std::string PANEL_NAME = "_notification_panel_";
-
-	LLPanel* old_panel = findChild<LLPanel>(PANEL_NAME);
-	if(old_panel)
+	// delete old form
+	if(mScriptForm)
 	{
-		removeChild(old_panel);
+		removeChild(mScriptForm);
+		mScriptForm->die();
 	}
 
 	LLNotificationPtr notification = LLNotifications::getInstance()->find(
-		LLScriptFloaterManager::getInstance()->getNotificationId(object_id));
+		LLScriptFloaterManager::getInstance()->findNotificationId(object_id));
 	if(NULL == notification)
 	{
 		return;
 	}
-	LLToastNotifyPanel* panel = new LLToastNotifyPanel(notification);
-	panel->setName(PANEL_NAME);
-	addChild(panel);
 
-	LLRect panel_rect;
+	// create new form
+	mScriptForm = new LLToastNotifyPanel(notification);
+	addChild(mScriptForm);
 
-	panel_rect = panel->getRect();
-	panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
-	reshape(panel_rect.getWidth(), panel_rect.getHeight());
-	panel->setRect(panel_rect);
+	// position form on floater
+	mScriptForm->setOrigin(0, 0);
 
+	// make floater size fit form size
 	LLRect toast_rect = getRect();
+	LLRect panel_rect = mScriptForm->getRect();
 	toast_rect.setLeftTopAndSize(toast_rect.mLeft, toast_rect.mTop, panel_rect.getWidth(), panel_rect.getHeight() + getHeaderHeight());
-	reshape(toast_rect.getWidth(), toast_rect.getHeight());
-	setRect(toast_rect);
+	setShape(toast_rect);
 }
 
 void LLScriptFloater::onClose(bool app_quitting)
 {
-	LLScriptFloaterManager::getInstance()->closeScriptFloater(getObjectId());
-	setObjectId(LLUUID::null);
+	LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(getObjectId());
 }
 
 void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */)
 {
 	LLTransientDockableFloater::setDocked(docked, pop_on_undock);
 
-	updateToasts();
+	hideToastsIfNeeded();
 }
 
 void LLScriptFloater::setVisible(BOOL visible)
 {
 	LLTransientDockableFloater::setVisible(visible);
 
-	updateToasts();
+	hideToastsIfNeeded();
 }
 
-void LLScriptFloater::updateToasts()
+void LLScriptFloater::hideToastsIfNeeded()
 {
 	using namespace LLNotificationsUI;
 
@@ -197,12 +195,12 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
 	LLUUID object_id = notification_id_to_object_id(notification_id);
 	if(object_id.isNull())
 	{
-		llerrs << "Invalid notification, no object id" << llendl;
+		llwarns << "Invalid notification, no object id" << llendl;
 		return;
 	}
 
 	// If an Object spawns more-than-one floater, only the newest one is shown. 
-	// The other is automatically closed.
+	// The previous is automatically closed.
 	script_notification_map_t::iterator it = mNotifications.find(object_id);
 	if(it != mNotifications.end())
 	{
@@ -220,18 +218,19 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id)
 	LLUUID object_id = notification_id_to_object_id(notification_id);
 	if(object_id.isNull())
 	{
-		llerrs << "Invalid notification, no object id" << llendl;
+		llwarns << "Invalid notification, no object id" << llendl;
 		return;
 	}
 
 	using namespace LLNotificationsUI;
 
 	// remove related toast
-	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID(
-		LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+	LLUUID channel_id(gSavedSettings.getString("NotificationChannelUUID"));
+	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>
+		(LLChannelManager::getInstance()->findChannelByID(channel_id));
 	if(channel)
 	{
-		channel->killToastByNotificationID(getToastNotificationId(object_id));
+		channel->killToastByNotificationID(findNotificationToastId(object_id));
 	}
 
 	mNotifications.erase(object_id);
@@ -247,6 +246,17 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id)
 	}
 }
 
+void LLScriptFloaterManager::removeNotificationByObjectId(const LLUUID& object_id)
+{
+	// Check we have not removed notification yet
+	LLNotificationPtr notification = LLNotifications::getInstance()->find(
+		findNotificationId(object_id));
+	if(notification)
+	{
+		onRemoveNotification(notification->getID());
+	}
+}
+
 void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id)
 {
 	// hide "new message" icon from chiclet
@@ -262,24 +272,14 @@ void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id)
 		LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
 	if(channel)
 	{
-		channel->killToastByNotificationID(getToastNotificationId(object_id));
+		channel->killToastByNotificationID(findNotificationToastId(object_id));
 	}
 
 	// toggle floater
 	LLScriptFloater::toggle(object_id);
 }
 
-void LLScriptFloaterManager::closeScriptFloater(const LLUUID& object_id)
-{
-	LLNotificationPtr notification = LLNotifications::getInstance()->find(
-		getNotificationId(object_id));
-	if(notification)
-	{
-		onRemoveNotification(notification->getID());
-	}
-}
-
-void LLScriptFloaterManager::setToastNotificationId(const LLUUID& object_id, const LLUUID& notification_id)
+void LLScriptFloaterManager::setNotificationToastId(const LLUUID& object_id, const LLUUID& notification_id)
 {
 	script_notification_map_t::iterator it = mNotifications.find(object_id);
 	if(mNotifications.end() != it)
@@ -288,7 +288,7 @@ void LLScriptFloaterManager::setToastNotificationId(const LLUUID& object_id, con
 	}
 }
 
-const LLUUID& LLScriptFloaterManager::getNotificationId(const LLUUID& object_id)
+LLUUID LLScriptFloaterManager::findNotificationId(const LLUUID& object_id)
 {
 	script_notification_map_t::const_iterator it = mNotifications.find(object_id);
 	if(mNotifications.end() != it)
@@ -298,7 +298,7 @@ const LLUUID& LLScriptFloaterManager::getNotificationId(const LLUUID& object_id)
 	return LLUUID::null;
 }
 
-const LLUUID& LLScriptFloaterManager::getToastNotificationId(const LLUUID& object_id)
+LLUUID LLScriptFloaterManager::findNotificationToastId(const LLUUID& object_id)
 {
 	script_notification_map_t::const_iterator it = mNotifications.find(object_id);
 	if(mNotifications.end() != it)
@@ -320,11 +320,11 @@ void LLScriptFloaterManager::onToastButtonClick(const LLSD&notification, const L
 		LLScriptFloaterManager::getInstance()->toggleScriptFloater(object_id);
 		break;
 	case 1: // "Ignore"
-		LLScriptFloaterManager::getInstance()->closeScriptFloater(object_id);
+		LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id);
 		break;
-	case 2: // "Mute"
+	case 2: // "Block"
 		LLMuteList::getInstance()->add(LLMute(object_id, notification["substitutions"]["TITLE"], LLMute::OBJECT));
-		LLScriptFloaterManager::getInstance()->closeScriptFloater(object_id);
+		LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id);
 		break;
 	default:
 		llwarns << "Unexpected value" << llendl;
diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h
index fc1d9a0186..0e1a7f36b7 100644
--- a/indra/newview/llscriptfloater.h
+++ b/indra/newview/llscriptfloater.h
@@ -35,27 +35,52 @@
 
 #include "lltransientdockablefloater.h"
 
+class LLToastNotifyPanel;
+
 /**
- * This class manages Object script floaters.
+ * Handles script notifications ("ScriptDialog" and "ScriptDialogGroup")
+ * and manages Script Floaters.
  */
 class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager>
 {
 public:
 
+	/**
+	 * Handles new notifications.
+	 * Saves notification and object ids, removes old notification if needed, creates script chiclet
+	 * Note that one object can spawn one script floater.
+	 */
 	void onAddNotification(const LLUUID& notification_id);
 
+	/**
+	 * Handles notification removal.
+	 * Removes script notification toast, removes script chiclet, closes script floater
+	 */
 	void onRemoveNotification(const LLUUID& notification_id);
 
-	void toggleScriptFloater(const LLUUID& object_id);
+	/**
+	 * Wrapper for onRemoveNotification, removes notification by object id.
+	 */
+	void removeNotificationByObjectId(const LLUUID& object_id);
 
-	void closeScriptFloater(const LLUUID& object_id);
+	/**
+	 * Toggles script floater.
+	 * Removes "new message" icon from chiclet and removes notification toast.
+	 */
+	void toggleScriptFloater(const LLUUID& object_id);
 
-	const LLUUID& getNotificationId(const LLUUID& object_id);
+	LLUUID findNotificationId(const LLUUID& object_id);
 
-	const LLUUID& getToastNotificationId(const LLUUID& object_id);
+	LLUUID findNotificationToastId(const LLUUID& object_id);
 
-	void setToastNotificationId(const LLUUID& object_id, const LLUUID& notification_id);
+	/**
+	 * Associate notification toast id with object id.
+	 */
+	void setNotificationToastId(const LLUUID& object_id, const LLUUID& notification_id);
 
+	/**
+	* Callback for notification toast buttons.
+	*/
 	static void onToastButtonClick(const LLSD&notification, const LLSD&response);
 
 private:
@@ -66,13 +91,16 @@ private:
 		LLUUID toast_notification_id;
 	};
 
+	// <object_id, notification_data>
 	typedef std::map<LLUUID, LLNotificationData> script_notification_map_t;
 
 	script_notification_map_t mNotifications;
 };
 
 /**
- * Floater for displaying script forms
+ * Floater script forms.
+ * LLScriptFloater will create script form based on notification data and 
+ * will auto fit the form.
  */
 class LLScriptFloater : public LLTransientDockableFloater
 {
@@ -85,29 +113,51 @@ public:
 
 	virtual ~LLScriptFloater(){};
 
+	/**
+	 * Toggle existing floater or create and show a new one.
+	 */
 	static bool toggle(const LLUUID& object_id);
 
+	/**
+	 * Creates and shows floater
+	 */
 	static LLScriptFloater* show(const LLUUID& object_id);
 
 	const LLUUID& getObjectId() { return mObjectId; }
 
+	/**
+	 * Close notification if script floater is closed.
+	 */
 	/*virtual*/ void onClose(bool app_quitting);
 
+	/**
+	 * Hide all notification toasts when we show dockable floater
+	 */
 	/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
 
+	/**
+	 * Hide all notification toasts when we show dockable floater
+	 */
 	/*virtual*/ void setVisible(BOOL visible);
 
 protected:
 
+	/**
+	 * Creates script form, will delete old form if floater is shown for same object.
+	 */
 	void createForm(const LLUUID& object_id);
 
 	/*virtual*/ void getAllowedRect(LLRect& rect);
 
-	static void updateToasts();
+	/**
+	 * Hide all notification toasts.
+	 */
+	static void hideToastsIfNeeded();
 
 	void setObjectId(const LLUUID& id) { mObjectId = id; }
 
 private:
+	LLToastNotifyPanel* mScriptForm;
 	LLUUID mObjectId;
 };
 
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ac1f366f9c..4d7d3ee8ac 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5382,13 +5382,15 @@ void process_script_dialog(LLMessageSystem* msg, void**)
 			LLNotification::Params("ScriptDialogGroup").substitutions(args).payload(payload).form_elements(form.asLLSD()));
 	}
 
+	// "ScriptDialog" and "ScriptDialogGroup" are handles by LLScriptFloaterManager.
+	// We want to inform user that there is a script floater, lets add "ScriptToast"
 	LLNotification::Params p("ScriptToast");
 	p.substitutions(args).payload(payload).functor.function(boost::bind(
 		LLScriptFloaterManager::onToastButtonClick, _1, _2));
 
 	notification = LLNotifications::instance().add(p);
 
-	LLScriptFloaterManager::getInstance()->setToastNotificationId(
+	LLScriptFloaterManager::getInstance()->setNotificationToastId(
 		object_id, notification->getID());
 }
 
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index af71ae09d2..238f3bdac8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5314,8 +5314,8 @@ Grant this request?
        text="Ignore"/>
       <button
        index="2"
-       name="Mute"
-       text="Mute"/>
+       name="Block"
+       text="Block"/>
     </form>
   </notification>
 
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
new file mode 100644
index 0000000000..5011bf6a61
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_script
+ name="script_chiclet">
+ <icon
+  name="chiclet_icon"
+  follows="all"
+  mouse_opaque="false"
+  image_name="Generic_Object_Small" />
+</expandable_text>
\ No newline at end of file
-- 
cgit v1.2.3