From 13a6077b780117be0fa3a054426d139ca1d35df9 Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan Date: Fri, 20 Nov 2009 19:17:38 +0200 Subject: Implemented normal task EXT-2081 - Object IM chiclets art needs to be hooked up to LLDialog chiclets. Implemented LLDialog(LLScriptFloater) and Script Chiclets. --HG-- branch : product-engine --- indra/newview/llscriptfloater.cpp | 335 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 indra/newview/llscriptfloater.cpp (limited to 'indra/newview/llscriptfloater.cpp') diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp new file mode 100644 index 0000000000..6fdde1df99 --- /dev/null +++ b/indra/newview/llscriptfloater.cpp @@ -0,0 +1,335 @@ +/** + * @file llscriptfloater.cpp + * @brief LLScriptFloater class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llscriptfloater.h" + +#include "llbottomtray.h" +#include "llchannelmanager.h" +#include "llchiclet.h" +#include "llfloaterreg.h" +#include "llscreenchannel.h" +#include "lltoastnotifypanel.h" +#include "llviewerwindow.h" + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLUUID notification_id_to_object_id(const LLUUID& notification_id) +{ + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(notification) + { + return notification->getPayload()["object_id"].asUUID(); + } + return LLUUID::null; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLScriptFloater::LLScriptFloater(const LLSD& key) +: LLTransientDockableFloater(NULL, true, key) +, mObjectId(key.asUUID()) +{ +} + +bool LLScriptFloater::toggle(const LLUUID& object_id) +{ + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", object_id); + + // show existing floater + if(floater) + { + if(floater->getVisible()) + { + floater->setVisible(false); + return false; + } + else + { + floater->setVisible(TRUE); + floater->setFocus(TRUE); + return true; + } + } + else + { + show(object_id); + return true; + } +} + +LLScriptFloater* LLScriptFloater::show(const LLUUID& object_id) +{ + LLScriptFloater* floater = LLFloaterReg::showTypedInstance("script_floater", object_id); + floater->createForm(object_id); + + if (floater->getDockControl() == NULL) + { + LLChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet(object_id); + if (chiclet == NULL) + { + llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); + } + else + { + LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); + } + + floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), + LLDockControl::TOP, boost::bind(&LLScriptFloater::getAllowedRect, floater, _1))); + } + + return floater; +} + +void LLScriptFloater::getAllowedRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRectRaw(); +} + +void LLScriptFloater::createForm(const LLUUID& object_id) +{ + static const std::string PANEL_NAME = "_notification_panel_"; + + LLPanel* old_panel = findChild(PANEL_NAME); + if(old_panel) + { + removeChild(old_panel); + } + + LLNotificationPtr notification = LLNotifications::getInstance()->find( + LLScriptFloaterManager::getInstance()->getNotificationId(object_id)); + if(NULL == notification) + { + return; + } + LLToastNotifyPanel* panel = new LLToastNotifyPanel(notification); + panel->setName(PANEL_NAME); + addChild(panel); + + LLRect panel_rect; + + 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); + + LLRect toast_rect = 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); +} + +void LLScriptFloater::onClose(bool app_quitting) +{ + LLScriptFloaterManager::getInstance()->closeScriptFloater(getObjectId()); + setObjectId(LLUUID::null); +} + +void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) +{ + LLTransientDockableFloater::setDocked(docked, pop_on_undock); + + updateToasts(); +} + +void LLScriptFloater::setVisible(BOOL visible) +{ + LLTransientDockableFloater::setVisible(visible); + + updateToasts(); +} + +void LLScriptFloater::updateToasts() +{ + using namespace LLNotificationsUI; + + // find channel + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) +{ + // get scripted Object's ID + LLUUID object_id = notification_id_to_object_id(notification_id); + if(object_id.isNull()) + { + llerrs << "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. + script_notification_map_t::iterator it = mNotifications.find(object_id); + if(it != mNotifications.end()) + { + removeNotification(notification_id); + } + + LLNotificationData nd = {notification_id}; + mNotifications.insert(std::make_pair(object_id, nd)); + + LLBottomTray::getInstance()->getChicletPanel()->createChiclet(object_id); +} + +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; + return; + } + + using namespace LLNotificationsUI; + + // remove related toast + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + if(channel) + { + channel->killToastByNotificationID(getToastNotificationId(object_id)); + } + + mNotifications.erase(object_id); + + // remove related chiclet + LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(object_id); + + // close floater + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", object_id); + if(floater) + { + floater->closeFloater(); + } +} + +void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id) +{ + // hide "new message" icon from chiclet + LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet(object_id); + if(chiclet) + { + chiclet->setShowNewMessagesIcon(false); + } + + // kill toast + using namespace LLNotificationsUI; + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + if(channel) + { + channel->killToastByNotificationID(getToastNotificationId(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) + { + removeNotification(notification->getID()); + } +} + +void LLScriptFloaterManager::setToastNotificationId(const LLUUID& object_id, const LLUUID& notification_id) +{ + script_notification_map_t::iterator it = mNotifications.find(object_id); + if(mNotifications.end() != it) + { + it->second.toast_notification_id = notification_id; + } +} + +const LLUUID& LLScriptFloaterManager::getNotificationId(const LLUUID& object_id) +{ + script_notification_map_t::const_iterator it = mNotifications.find(object_id); + if(mNotifications.end() != it) + { + return it->second.notification_id; + } + return LLUUID::null; +} + +const LLUUID& LLScriptFloaterManager::getToastNotificationId(const LLUUID& object_id) +{ + script_notification_map_t::const_iterator it = mNotifications.find(object_id); + if(mNotifications.end() != it) + { + return it->second.toast_notification_id; + } + return LLUUID::null; +} + +//static +void LLScriptFloaterManager::onToastButtonClick(const LLSD¬ification, const LLSD&response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLUUID object_id = notification["payload"]["object_id"].asUUID(); + + switch(option) + { + case 0: // "Open" + LLScriptFloaterManager::getInstance()->toggleScriptFloater(object_id); + break; + case 1: // "Ignore" + LLScriptFloaterManager::getInstance()->closeScriptFloater(object_id); + break; + case 2: // "Mute" + LLMuteList::getInstance()->add(LLMute(object_id, notification["substitutions"]["TITLE"], LLMute::OBJECT)); + LLScriptFloaterManager::getInstance()->closeScriptFloater(object_id); + break; + default: + llwarns << "Unexpected value" << llendl; + break; + } +} + +// EOF -- cgit v1.3 From 9d64bf132e27739dedeca17a1d952655c6b52ac3 Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan Date: Fri, 20 Nov 2009 19:23:22 +0200 Subject: Update for normal task EXT-2081 - Object IM chiclets art needs to be hooked up to LLDialog chiclets. Fixed function names. --HG-- branch : product-engine --- indra/newview/llnotificationscripthandler.cpp | 2 +- indra/newview/llscriptfloater.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llscriptfloater.cpp') diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 84a8191375..6cd5ee8f43 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -120,7 +120,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify) mChannel->killToastByNotificationID(notification->getID()); if("ScriptDialog" == notification->getName()) { - LLScriptFloaterManager::getInstance()->removeNotification(notification->getID()); + LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } } return true; diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 6fdde1df99..1bf6235d04 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -206,7 +206,7 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) script_notification_map_t::iterator it = mNotifications.find(object_id); if(it != mNotifications.end()) { - removeNotification(notification_id); + onRemoveNotification(notification_id); } LLNotificationData nd = {notification_id}; @@ -275,7 +275,7 @@ void LLScriptFloaterManager::closeScriptFloater(const LLUUID& object_id) getNotificationId(object_id)); if(notification) { - removeNotification(notification->getID()); + onRemoveNotification(notification->getID()); } } -- cgit v1.3 From 9f0dbcf4c0c6c8621c377fd7f9e417aa76acd836 Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan 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 (limited to 'indra/newview/llscriptfloater.cpp') 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 t2("chiclet_notif static LLDefaultChildRegistry::Register t3("chiclet_im_p2p"); static LLDefaultChildRegistry::Register t4("chiclet_im_group"); static LLDefaultChildRegistry::Register t5("chiclet_im_adhoc"); +static LLDefaultChildRegistry::Register 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(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 { - Optional avatar_icon; + Optional 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 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(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(LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + LLUUID channel_id(gSavedSettings.getString("NotificationChannelUUID")); + LLScreenChannel* channel = dynamic_cast + (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¬ification, 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 { 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¬ification, const LLSD&response); private: @@ -66,13 +91,16 @@ private: LLUUID toast_notification_id; }; + // typedef std::map 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"/>