/** * @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) , mScriptForm(NULL) , 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; } } // create and show new floater 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) { // delete old form if(mScriptForm) { removeChild(mScriptForm); mScriptForm->die(); } LLNotificationPtr notification = LLNotifications::getInstance()->find( LLScriptFloaterManager::getInstance()->findNotificationId(object_id)); if(NULL == notification) { return; } // create new form mScriptForm = new LLToastNotifyPanel(notification); addChild(mScriptForm); // 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()); setShape(toast_rect); } void LLScriptFloater::onClose(bool app_quitting) { LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(getObjectId()); } void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) { LLTransientDockableFloater::setDocked(docked, pop_on_undock); hideToastsIfNeeded(); } void LLScriptFloater::setVisible(BOOL visible) { LLTransientDockableFloater::setVisible(visible); hideToastsIfNeeded(); } void LLScriptFloater::hideToastsIfNeeded() { 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()) { llwarns << "Invalid notification, no object id" << llendl; return; } // If an Object spawns more-than-one floater, only the newest one is shown. // The previous is automatically closed. script_notification_map_t::iterator it = mNotifications.find(object_id); if(it != mNotifications.end()) { onRemoveNotification(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()) { llwarns << "Invalid notification, no object id" << llendl; return; } using namespace LLNotificationsUI; // remove related toast LLUUID channel_id(gSavedSettings.getString("NotificationChannelUUID")); LLScreenChannel* channel = dynamic_cast (LLChannelManager::getInstance()->findChannelByID(channel_id)); if(channel) { channel->killToastByNotificationID(findNotificationToastId(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::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 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(findNotificationToastId(object_id)); } // toggle floater LLScriptFloater::toggle(object_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) { it->second.toast_notification_id = notification_id; } } LLUUID LLScriptFloaterManager::findNotificationId(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; } LLUUID LLScriptFloaterManager::findNotificationToastId(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()->removeNotificationByObjectId(object_id); break; case 2: // "Block" LLMuteList::getInstance()->add(LLMute(object_id, notification["substitutions"]["TITLE"], LLMute::OBJECT)); LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id); break; default: llwarns << "Unexpected value" << llendl; break; } } // EOF