From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llscriptfloater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llscriptfloater.cpp') diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 6a27ff3047..9d7e8623e5 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -205,7 +205,7 @@ void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) hideToastsIfNeeded(); } -void LLScriptFloater::setVisible(BOOL visible) +void LLScriptFloater::setVisible(bool visible) { LLDockableFloater::setVisible(visible); -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llscriptfloater.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/llscriptfloater.cpp') diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 9d7e8623e5..d714017e01 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -87,8 +87,8 @@ bool LLScriptFloater::toggle(const LLUUID& notification_id) } else { - floater->setVisible(TRUE); - floater->setFocus(FALSE); + floater->setVisible(true); + floater->setFocus(false); } } // create and show new floater @@ -113,7 +113,7 @@ LLScriptFloater* LLScriptFloater::show(const LLUUID& notification_id) floater->createForm(notification_id); //LLDialog(LLGiveInventory and LLLoadURL) should no longer steal focus (see EXT-5445) - floater->setAutoFocus(FALSE); + floater->setAutoFocus(false); if(LLScriptFloaterManager::OBJ_SCRIPT == LLScriptFloaterManager::getObjectType(notification_id)) { @@ -126,7 +126,7 @@ LLScriptFloater* LLScriptFloater::show(const LLUUID& notification_id) } //LLDialog(LLGiveInventory and LLLoadURL) should no longer steal focus (see EXT-5445) - LLFloaterReg::showTypedInstance("script_floater", notification_id, FALSE); + LLFloaterReg::showTypedInstance("script_floater", notification_id, false); return floater; } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llscriptfloater.cpp | 1556 ++++++++++++++++++------------------- 1 file changed, 778 insertions(+), 778 deletions(-) (limited to 'indra/newview/llscriptfloater.cpp') diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 64e4502563..22a9dd0027 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -1,778 +1,778 @@ -/** - * @file llscriptfloater.cpp - * @brief LLScriptFloater class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llscriptfloater.h" -#include "llagentcamera.h" - -#include "llchannelmanager.h" -#include "llchiclet.h" -#include "llchicletbar.h" -#include "llfloaterreg.h" -#include "lllslconstants.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" -#include "llscreenchannel.h" -#include "llsyswellwindow.h" -#include "lltoastnotifypanel.h" -#include "lltoastscripttextbox.h" -#include "lltrans.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llfloaterimsession.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) -: LLDockableFloater(NULL, true, key) -, mScriptForm(NULL) -, mSaveFloaterPosition(false) -{ - setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); - setOverlapsScreenChannel(true); - mIsDockedStateForcedCallback = boost::bind(&LLAgentCamera::cameraMouselook, &gAgentCamera); -} - -bool LLScriptFloater::toggle(const LLUUID& notification_id) -{ - LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", notification_id); - - // show existing floater - if(floater) - { - if(floater->getVisible()) - { - floater->setVisible(false); - return false; - } - else - { - floater->setVisible(true); - floater->setFocus(false); - } - } - // create and show new floater - else - { - show(notification_id); - } - - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - chiclet_panelp->setChicletToggleState(notification_id, true); - } - - return true; -} - -LLScriptFloater* LLScriptFloater::show(const LLUUID& notification_id) -{ - LLScriptFloater* floater = LLFloaterReg::getTypedInstance("script_floater", notification_id); - floater->setNotificationId(notification_id); - floater->createForm(notification_id); - - //LLDialog(LLGiveInventory and LLLoadURL) should no longer steal focus (see EXT-5445) - floater->setAutoFocus(false); - - if(LLScriptFloaterManager::OBJ_SCRIPT == LLScriptFloaterManager::getObjectType(notification_id)) - { - floater->setSavePosition(true); - floater->restorePosition(); - } - else - { - floater->dockToChiclet(true); - } - - //LLDialog(LLGiveInventory and LLLoadURL) should no longer steal focus (see EXT-5445) - LLFloaterReg::showTypedInstance("script_floater", notification_id, false); - - return floater; -} - -void LLScriptFloater::setNotificationId(const LLUUID& id) -{ - mNotificationId = id; - // Lets save object id now while notification exists - mObjectId = notification_id_to_object_id(id); -} - -void LLScriptFloater::createForm(const LLUUID& notification_id) -{ - // delete old form - if(mScriptForm) - { - removeChild(mScriptForm); - mScriptForm->die(); - } - - LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); - if(NULL == notification) - { - return; - } - - // create new form - LLRect toast_rect = getRect(); - if (isScriptTextbox(notification)) - { - mScriptForm = new LLToastScriptTextbox(notification); - } - else - { - // LLToastNotifyPanel will fit own content in vertical direction, - // but it needs an initial rect to properly calculate its width - // Use an initial rect of the script floater to make the floater - // window more configurable. - mScriptForm = new LLToastNotifyPanel(notification, toast_rect); - } - addChild(mScriptForm); - - // position form on floater - mScriptForm->setOrigin(0, 0); - - // make floater size fit form size - 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) -{ - savePosition(); - - if(getNotificationId().notNull()) - { - // we shouldn't kill notification on exit since it may be used as persistent. - if (app_quitting) - { - LLScriptFloaterManager::getInstance()->onRemoveNotification(getNotificationId()); - } - else - { - LLScriptFloaterManager::getInstance()->removeNotification(getNotificationId()); - } - } -} - -void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) -{ - LLDockableFloater::setDocked(docked, pop_on_undock); - - savePosition(); - - hideToastsIfNeeded(); -} - -void LLScriptFloater::setVisible(bool visible) -{ - LLDockableFloater::setVisible(visible); - - hideToastsIfNeeded(); - - if(!visible) - { - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - LLIMChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); - if(NULL != chicletp) - { - chicletp->setToggleState(false); - } - } - } -} - -void LLScriptFloater::onMouseDown() -{ - if(getNotificationId().notNull()) - { - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - LLIMChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); - // Remove new message icon - if (NULL == chicletp) - { - LL_ERRS() << "Dock chiclet for LLScriptFloater doesn't exist" << LL_ENDL; - } - else - { - chicletp->setShowNewMessagesIcon(false); - } - } - } -} - -void LLScriptFloater::savePosition() -{ - if(getSavePosition() && mObjectId.notNull()) - { - LLScriptFloaterManager::FloaterPositionInfo fpi = {getRect(), isDocked()}; - LLScriptFloaterManager::getInstance()->saveFloaterPosition(mObjectId, fpi); - } -} - -void LLScriptFloater::restorePosition() -{ - LLScriptFloaterManager::FloaterPositionInfo fpi; - if(LLScriptFloaterManager::getInstance()->getFloaterPosition(mObjectId, fpi)) - { - dockToChiclet(fpi.mDockState); - if(!fpi.mDockState) - { - // Un-docked floater is opened in 0,0, now move it to saved position - translate(fpi.mRect.mLeft - getRect().mLeft, fpi.mRect.mTop - getRect().mTop); - } - } - else - { - dockToChiclet(true); - } -} - -void LLScriptFloater::onFocusLost() -{ - if(getNotificationId().notNull()) - { - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - chiclet_panelp->setChicletToggleState(getNotificationId(), false); - } - } -} - -void LLScriptFloater::onFocusReceived() -{ - // first focus will be received before setObjectId() call - don't toggle chiclet - if(getNotificationId().notNull()) - { - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - chiclet_panelp->setChicletToggleState(getNotificationId(), true); - } - } -} - -void LLScriptFloater::dockToChiclet(bool dock) -{ - if (getDockControl() == NULL) - { - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - LLChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); - if (NULL == chicletp) - { - LL_WARNS() << "Dock chiclet for LLScriptFloater doesn't exist" << LL_ENDL; - return; - } - - chiclet_panelp->scrollToChiclet(chicletp); - - // Stop saving position while we dock floater - bool save = getSavePosition(); - setSavePosition(false); - - setDockControl(new LLDockControl(chicletp, this, getDockTongue(), - LLDockControl::BOTTOM)); - - setDocked(dock); - - // Restore saving - setSavePosition(save); - } - } -} - -void LLScriptFloater::hideToastsIfNeeded() -{ - using namespace LLNotificationsUI; - - // find channel - LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( - LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); - // update notification channel state - if(channel) - { - channel->updateShowToastsState(); - channel->redrawToasts(); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLScriptFloaterManager::LLScriptFloaterManager() - : mDialogLimitationsSlot() -{ -} - -void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) -{ - if(notification_id.isNull()) - { - LL_WARNS() << "Invalid notification ID" << LL_ENDL; - return; - } - - if (!mDialogLimitationsSlot.connected()) - { - LLPointer cntrl_ptr = gSavedSettings.getControl("ScriptDialogLimitations"); - if (cntrl_ptr.notNull()) - { - mDialogLimitationsSlot = cntrl_ptr->getCommitSignal()->connect(boost::bind(&clearScriptNotifications)); - } - else - { - LL_WARNS() << "Unable to set signal on setting 'ScriptDialogLimitations'" << LL_ENDL; - } - } - - // get scripted Object's ID - LLUUID object_id = notification_id_to_object_id(notification_id); - - // Need to indicate of "new message" for object chiclets according to requirements - // specified in the Message Bar design specification. See EXT-3142. - bool set_new_message = false; - EObjectType obj_type = getObjectType(notification_id); - - // LLDialog can spawn only one instance, LLLoadURL and LLGiveInventory can spawn unlimited number of instances - if(OBJ_SCRIPT == obj_type) - { - static LLCachedControl script_dialog_limitations(gSavedSettings, "ScriptDialogLimitations", 0); - script_notification_map_t::const_iterator it = mNotifications.end(); - switch (script_dialog_limitations) - { - case SCRIPT_PER_CHANNEL: - { - // If an Object spawns more-than-one floater per channel, only the newest one is shown. - // The previous is automatically closed. - LLNotificationPtr notification = LLNotifications::instance().find(notification_id); - if (notification) - { - it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); - } - break; - } - case SCRIPT_ATTACHMENT_PER_CHANNEL: - { - LLViewerObject* objectp = gObjectList.findObject(object_id); - if (objectp && objectp->getAttachmentItemID().notNull()) //in user inventory - { - LLNotificationPtr notification = LLNotifications::instance().find(notification_id); - if (notification) - { - it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); - } - } - else - { - it = findUsingObjectId(object_id); - } - break; - } - case SCRIPT_HUD_PER_CHANNEL: - { - LLViewerObject* objectp = gObjectList.findObject(object_id); - if (objectp && objectp->isHUDAttachment()) - { - LLNotificationPtr notification = LLNotifications::instance().find(notification_id); - if (notification) - { - it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); - } - } - else - { - it = findUsingObjectId(object_id); - } - break; - } - case SCRIPT_HUD_UNCONSTRAINED: - { - LLViewerObject* objectp = gObjectList.findObject(object_id); - if (objectp && objectp->isHUDAttachment()) - { - // don't remove existing floaters - break; - } - else - { - it = findUsingObjectId(object_id); - } - break; - } - case SCRIPT_PER_OBJECT: - default: - { - // If an Object spawns more-than-one floater, only the newest one is shown. - // The previous is automatically closed. - it = findUsingObjectId(object_id); - break; - } - } - - if(it != mNotifications.end()) - { - LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - LLIMChiclet * chicletp = chiclet_panelp->findChiclet(old_id); - if (NULL != chicletp) - { - // Pass the new_message icon state further. - set_new_message = chicletp->getShowNewMessagesIcon(); - chicletp->hidePopupMenu(); - } - } - - LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", old_id); - if (floater) - { - // Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142. - set_new_message |= !floater->hasFocus(); - } - - removeNotification(old_id); - } - } - - mNotifications.insert(std::make_pair(notification_id, object_id)); - - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - // Create inventory offer chiclet for offer type notifications - if( OBJ_GIVE_INVENTORY == obj_type ) - { - chiclet_panelp->createChiclet(notification_id); - } - else - { - chiclet_panelp->createChiclet(notification_id); - } - } - - LLIMWellWindow::getInstance()->addObjectRow(notification_id, set_new_message); - - LLSD data; - data["notification_id"] = notification_id; - data["new_message"] = set_new_message; - data["unread"] = 1; // each object has got only one floater - mNewObjectSignal(data); - - toggleScriptFloater(notification_id, set_new_message); -} - -void LLScriptFloaterManager::removeNotification(const LLUUID& notification_id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(notification_id); - if (notification != NULL && !notification->isCancelled()) - { - LLNotificationsUtil::cancel(notification); - } - - onRemoveNotification(notification_id); -} - -void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) -{ - if(notification_id.isNull()) - { - LL_WARNS() << "Invalid notification ID" << LL_ENDL; - return; - } - - // remove related chiclet - if (LLChicletBar::instanceExists()) - { - LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); - if (NULL != chiclet_panelp) - { - chiclet_panelp->removeChiclet(notification_id); - } - } - - LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance(); - if (im_well_window) - { - im_well_window->removeObjectRow(notification_id); - } - - mNotifications.erase(notification_id); - - // close floater - LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", notification_id); - if(floater) - { - floater->savePosition(); - floater->setNotificationId(LLUUID::null); - floater->closeFloater(); - } -} - -void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& notification_id, bool set_new_message) -{ - LLSD data; - data["notification_id"] = notification_id; - data["new_message"] = set_new_message; - mToggleFloaterSignal(data); - - // toggle floater - LLScriptFloater::toggle(notification_id); -} - -LLUUID LLScriptFloaterManager::findObjectId(const LLUUID& notification_id) -{ - script_notification_map_t::const_iterator it = mNotifications.find(notification_id); - if(mNotifications.end() != it) - { - return it->second; - } - return LLUUID::null; -} - -LLUUID LLScriptFloaterManager::findNotificationId(const LLUUID& object_id) -{ - if(object_id.notNull()) - { - script_notification_map_t::const_iterator it = findUsingObjectId(object_id); - if(mNotifications.end() != it) - { - return it->first; - } - } - return LLUUID::null; -} - -// static -LLScriptFloaterManager::EObjectType LLScriptFloaterManager::getObjectType(const LLUUID& notification_id) -{ - if(notification_id.isNull()) - { - LL_WARNS() << "Invalid notification ID" << LL_ENDL; - return OBJ_UNKNOWN; - } - - static const object_type_map TYPE_MAP = initObjectTypeMap(); - - LLNotificationPtr notification = LLNotificationsUtil::find(notification_id); - object_type_map::const_iterator it = TYPE_MAP.find(notification->getName()); - if(it != TYPE_MAP.end()) - { - return it->second; - } - - LL_WARNS() << "Unknown object type" << LL_ENDL; - return OBJ_UNKNOWN; -} - -// static -std::string LLScriptFloaterManager::getObjectName(const LLUUID& notification_id) -{ - using namespace LLNotificationsUI; - LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); - if(!notification) - { - LL_WARNS() << "Invalid notification" << LL_ENDL; - return LLStringUtil::null; - } - - std::string text; - - switch(LLScriptFloaterManager::getObjectType(notification_id)) - { - case LLScriptFloaterManager::OBJ_SCRIPT: - text = notification->getSubstitutions()["TITLE"].asString(); - break; - case LLScriptFloaterManager::OBJ_LOAD_URL: - text = notification->getSubstitutions()["OBJECTNAME"].asString(); - break; - case LLScriptFloaterManager::OBJ_GIVE_INVENTORY: - text = notification->getSubstitutions()["OBJECTFROMNAME"].asString(); - break; - default: - text = LLTrans::getString("object"); - break; - } - - return text; -} - -//static -LLScriptFloaterManager::object_type_map LLScriptFloaterManager::initObjectTypeMap() -{ - object_type_map type_map; - type_map["ScriptDialog"] = OBJ_SCRIPT; - type_map["ScriptDialogGroup"] = OBJ_SCRIPT; - type_map["LoadWebPage"] = OBJ_LOAD_URL; - type_map["ObjectGiveItem"] = OBJ_GIVE_INVENTORY; - return type_map; -} - -LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloaterManager::findUsingObjectId(const LLUUID& object_id) -{ - script_notification_map_t::const_iterator it = mNotifications.begin(); - for(; mNotifications.end() != it; ++it) - { - if(object_id == it->second) - { - return it; - } - } - return mNotifications.end(); -} - -LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloaterManager::findUsingObjectIdAndChannel(const LLUUID& object_id, S32 im_channel) -{ - script_notification_map_t::const_iterator it = mNotifications.begin(); - for (; mNotifications.end() != it; ++it) - { - if (object_id == it->second) - { - LLNotificationPtr notification = LLNotifications::instance().find(it->first); - if (notification && (im_channel == notification->getPayload()["chat_channel"].asInteger())) - { - return it; - } - } - } - return mNotifications.end(); -} - -void LLScriptFloaterManager::saveFloaterPosition(const LLUUID& object_id, const FloaterPositionInfo& fpi) -{ - if(object_id.notNull()) - { - LLScriptFloaterManager::getInstance()->mFloaterPositions[object_id] = fpi; - } - else - { - LL_WARNS() << "Invalid object id" << LL_ENDL; - } -} - -bool LLScriptFloaterManager::getFloaterPosition(const LLUUID& object_id, FloaterPositionInfo& fpi) -{ - floater_position_map_t::const_iterator it = mFloaterPositions.find(object_id); - if(LLScriptFloaterManager::getInstance()->mFloaterPositions.end() != it) - { - fpi = it->second; - return true; - } - return false; -} - -void LLScriptFloaterManager::setFloaterVisible(const LLUUID& notification_id, bool visible) -{ - LLScriptFloater* floater = LLFloaterReg::findTypedInstance( - "script_floater", notification_id); - if(floater) - { - floater->setVisible(visible); - } -} - -//static -void LLScriptFloaterManager::clearScriptNotifications() -{ - LLScriptFloaterManager* inst = LLScriptFloaterManager::getInstance(); - static const object_type_map TYPE_MAP = initObjectTypeMap(); - - script_notification_map_t::const_iterator ntf_it = inst->mNotifications.begin(); - while (inst->mNotifications.end() != ntf_it) - { - LLUUID notification_id = ntf_it->first; - ntf_it++; // onRemoveNotification() erases notification - LLNotificationPtr notification = LLNotifications::instance().find(notification_id); - if (notification) - { - object_type_map::const_iterator map_it = TYPE_MAP.find(notification->getName()); - if (map_it != TYPE_MAP.end() && map_it->second == OBJ_SCRIPT) - { - if (notification != NULL && !notification->isCancelled()) - { - LLNotificationsUtil::cancel(notification); - } - inst->onRemoveNotification(notification_id); - } - } - } -} - -////////////////////////////////////////////////////////////////// - -bool LLScriptFloater::isScriptTextbox(LLNotificationPtr notification) -{ - // get a form for the notification - LLNotificationFormPtr form(notification->getForm()); - - if (form) - { - // get number of elements in the form - int num_options = form->getNumElements(); - - // if ANY of the buttons have the magic lltextbox string as - // name, then treat the whole dialog as a simple text entry - // box (i.e. mixed button and textbox forms are not supported) - for (int i=0; igetElement(i); - if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) - { - return true; - } - } - } - - return false; -} - -// EOF +/** + * @file llscriptfloater.cpp + * @brief LLScriptFloater class definition + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llscriptfloater.h" +#include "llagentcamera.h" + +#include "llchannelmanager.h" +#include "llchiclet.h" +#include "llchicletbar.h" +#include "llfloaterreg.h" +#include "lllslconstants.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llscreenchannel.h" +#include "llsyswellwindow.h" +#include "lltoastnotifypanel.h" +#include "lltoastscripttextbox.h" +#include "lltrans.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llfloaterimsession.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) +: LLDockableFloater(NULL, true, key) +, mScriptForm(NULL) +, mSaveFloaterPosition(false) +{ + setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); + setOverlapsScreenChannel(true); + mIsDockedStateForcedCallback = boost::bind(&LLAgentCamera::cameraMouselook, &gAgentCamera); +} + +bool LLScriptFloater::toggle(const LLUUID& notification_id) +{ + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", notification_id); + + // show existing floater + if(floater) + { + if(floater->getVisible()) + { + floater->setVisible(false); + return false; + } + else + { + floater->setVisible(true); + floater->setFocus(false); + } + } + // create and show new floater + else + { + show(notification_id); + } + + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(notification_id, true); + } + + return true; +} + +LLScriptFloater* LLScriptFloater::show(const LLUUID& notification_id) +{ + LLScriptFloater* floater = LLFloaterReg::getTypedInstance("script_floater", notification_id); + floater->setNotificationId(notification_id); + floater->createForm(notification_id); + + //LLDialog(LLGiveInventory and LLLoadURL) should no longer steal focus (see EXT-5445) + floater->setAutoFocus(false); + + if(LLScriptFloaterManager::OBJ_SCRIPT == LLScriptFloaterManager::getObjectType(notification_id)) + { + floater->setSavePosition(true); + floater->restorePosition(); + } + else + { + floater->dockToChiclet(true); + } + + //LLDialog(LLGiveInventory and LLLoadURL) should no longer steal focus (see EXT-5445) + LLFloaterReg::showTypedInstance("script_floater", notification_id, false); + + return floater; +} + +void LLScriptFloater::setNotificationId(const LLUUID& id) +{ + mNotificationId = id; + // Lets save object id now while notification exists + mObjectId = notification_id_to_object_id(id); +} + +void LLScriptFloater::createForm(const LLUUID& notification_id) +{ + // delete old form + if(mScriptForm) + { + removeChild(mScriptForm); + mScriptForm->die(); + } + + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(NULL == notification) + { + return; + } + + // create new form + LLRect toast_rect = getRect(); + if (isScriptTextbox(notification)) + { + mScriptForm = new LLToastScriptTextbox(notification); + } + else + { + // LLToastNotifyPanel will fit own content in vertical direction, + // but it needs an initial rect to properly calculate its width + // Use an initial rect of the script floater to make the floater + // window more configurable. + mScriptForm = new LLToastNotifyPanel(notification, toast_rect); + } + addChild(mScriptForm); + + // position form on floater + mScriptForm->setOrigin(0, 0); + + // make floater size fit form size + 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) +{ + savePosition(); + + if(getNotificationId().notNull()) + { + // we shouldn't kill notification on exit since it may be used as persistent. + if (app_quitting) + { + LLScriptFloaterManager::getInstance()->onRemoveNotification(getNotificationId()); + } + else + { + LLScriptFloaterManager::getInstance()->removeNotification(getNotificationId()); + } + } +} + +void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) +{ + LLDockableFloater::setDocked(docked, pop_on_undock); + + savePosition(); + + hideToastsIfNeeded(); +} + +void LLScriptFloater::setVisible(bool visible) +{ + LLDockableFloater::setVisible(visible); + + hideToastsIfNeeded(); + + if(!visible) + { + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); + if(NULL != chicletp) + { + chicletp->setToggleState(false); + } + } + } +} + +void LLScriptFloater::onMouseDown() +{ + if(getNotificationId().notNull()) + { + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); + // Remove new message icon + if (NULL == chicletp) + { + LL_ERRS() << "Dock chiclet for LLScriptFloater doesn't exist" << LL_ENDL; + } + else + { + chicletp->setShowNewMessagesIcon(false); + } + } + } +} + +void LLScriptFloater::savePosition() +{ + if(getSavePosition() && mObjectId.notNull()) + { + LLScriptFloaterManager::FloaterPositionInfo fpi = {getRect(), isDocked()}; + LLScriptFloaterManager::getInstance()->saveFloaterPosition(mObjectId, fpi); + } +} + +void LLScriptFloater::restorePosition() +{ + LLScriptFloaterManager::FloaterPositionInfo fpi; + if(LLScriptFloaterManager::getInstance()->getFloaterPosition(mObjectId, fpi)) + { + dockToChiclet(fpi.mDockState); + if(!fpi.mDockState) + { + // Un-docked floater is opened in 0,0, now move it to saved position + translate(fpi.mRect.mLeft - getRect().mLeft, fpi.mRect.mTop - getRect().mTop); + } + } + else + { + dockToChiclet(true); + } +} + +void LLScriptFloater::onFocusLost() +{ + if(getNotificationId().notNull()) + { + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(getNotificationId(), false); + } + } +} + +void LLScriptFloater::onFocusReceived() +{ + // first focus will be received before setObjectId() call - don't toggle chiclet + if(getNotificationId().notNull()) + { + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(getNotificationId(), true); + } + } +} + +void LLScriptFloater::dockToChiclet(bool dock) +{ + if (getDockControl() == NULL) + { + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + LLChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); + if (NULL == chicletp) + { + LL_WARNS() << "Dock chiclet for LLScriptFloater doesn't exist" << LL_ENDL; + return; + } + + chiclet_panelp->scrollToChiclet(chicletp); + + // Stop saving position while we dock floater + bool save = getSavePosition(); + setSavePosition(false); + + setDockControl(new LLDockControl(chicletp, this, getDockTongue(), + LLDockControl::BOTTOM)); + + setDocked(dock); + + // Restore saving + setSavePosition(save); + } + } +} + +void LLScriptFloater::hideToastsIfNeeded() +{ + using namespace LLNotificationsUI; + + // find channel + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + channel->redrawToasts(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLScriptFloaterManager::LLScriptFloaterManager() + : mDialogLimitationsSlot() +{ +} + +void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) +{ + if(notification_id.isNull()) + { + LL_WARNS() << "Invalid notification ID" << LL_ENDL; + return; + } + + if (!mDialogLimitationsSlot.connected()) + { + LLPointer cntrl_ptr = gSavedSettings.getControl("ScriptDialogLimitations"); + if (cntrl_ptr.notNull()) + { + mDialogLimitationsSlot = cntrl_ptr->getCommitSignal()->connect(boost::bind(&clearScriptNotifications)); + } + else + { + LL_WARNS() << "Unable to set signal on setting 'ScriptDialogLimitations'" << LL_ENDL; + } + } + + // get scripted Object's ID + LLUUID object_id = notification_id_to_object_id(notification_id); + + // Need to indicate of "new message" for object chiclets according to requirements + // specified in the Message Bar design specification. See EXT-3142. + bool set_new_message = false; + EObjectType obj_type = getObjectType(notification_id); + + // LLDialog can spawn only one instance, LLLoadURL and LLGiveInventory can spawn unlimited number of instances + if(OBJ_SCRIPT == obj_type) + { + static LLCachedControl script_dialog_limitations(gSavedSettings, "ScriptDialogLimitations", 0); + script_notification_map_t::const_iterator it = mNotifications.end(); + switch (script_dialog_limitations) + { + case SCRIPT_PER_CHANNEL: + { + // If an Object spawns more-than-one floater per channel, only the newest one is shown. + // The previous is automatically closed. + LLNotificationPtr notification = LLNotifications::instance().find(notification_id); + if (notification) + { + it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); + } + break; + } + case SCRIPT_ATTACHMENT_PER_CHANNEL: + { + LLViewerObject* objectp = gObjectList.findObject(object_id); + if (objectp && objectp->getAttachmentItemID().notNull()) //in user inventory + { + LLNotificationPtr notification = LLNotifications::instance().find(notification_id); + if (notification) + { + it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); + } + } + else + { + it = findUsingObjectId(object_id); + } + break; + } + case SCRIPT_HUD_PER_CHANNEL: + { + LLViewerObject* objectp = gObjectList.findObject(object_id); + if (objectp && objectp->isHUDAttachment()) + { + LLNotificationPtr notification = LLNotifications::instance().find(notification_id); + if (notification) + { + it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); + } + } + else + { + it = findUsingObjectId(object_id); + } + break; + } + case SCRIPT_HUD_UNCONSTRAINED: + { + LLViewerObject* objectp = gObjectList.findObject(object_id); + if (objectp && objectp->isHUDAttachment()) + { + // don't remove existing floaters + break; + } + else + { + it = findUsingObjectId(object_id); + } + break; + } + case SCRIPT_PER_OBJECT: + default: + { + // If an Object spawns more-than-one floater, only the newest one is shown. + // The previous is automatically closed. + it = findUsingObjectId(object_id); + break; + } + } + + if(it != mNotifications.end()) + { + LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(old_id); + if (NULL != chicletp) + { + // Pass the new_message icon state further. + set_new_message = chicletp->getShowNewMessagesIcon(); + chicletp->hidePopupMenu(); + } + } + + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", old_id); + if (floater) + { + // Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142. + set_new_message |= !floater->hasFocus(); + } + + removeNotification(old_id); + } + } + + mNotifications.insert(std::make_pair(notification_id, object_id)); + + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + // Create inventory offer chiclet for offer type notifications + if( OBJ_GIVE_INVENTORY == obj_type ) + { + chiclet_panelp->createChiclet(notification_id); + } + else + { + chiclet_panelp->createChiclet(notification_id); + } + } + + LLIMWellWindow::getInstance()->addObjectRow(notification_id, set_new_message); + + LLSD data; + data["notification_id"] = notification_id; + data["new_message"] = set_new_message; + data["unread"] = 1; // each object has got only one floater + mNewObjectSignal(data); + + toggleScriptFloater(notification_id, set_new_message); +} + +void LLScriptFloaterManager::removeNotification(const LLUUID& notification_id) +{ + LLNotificationPtr notification = LLNotifications::instance().find(notification_id); + if (notification != NULL && !notification->isCancelled()) + { + LLNotificationsUtil::cancel(notification); + } + + onRemoveNotification(notification_id); +} + +void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) +{ + if(notification_id.isNull()) + { + LL_WARNS() << "Invalid notification ID" << LL_ENDL; + return; + } + + // remove related chiclet + if (LLChicletBar::instanceExists()) + { + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->removeChiclet(notification_id); + } + } + + LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance(); + if (im_well_window) + { + im_well_window->removeObjectRow(notification_id); + } + + mNotifications.erase(notification_id); + + // close floater + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", notification_id); + if(floater) + { + floater->savePosition(); + floater->setNotificationId(LLUUID::null); + floater->closeFloater(); + } +} + +void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& notification_id, bool set_new_message) +{ + LLSD data; + data["notification_id"] = notification_id; + data["new_message"] = set_new_message; + mToggleFloaterSignal(data); + + // toggle floater + LLScriptFloater::toggle(notification_id); +} + +LLUUID LLScriptFloaterManager::findObjectId(const LLUUID& notification_id) +{ + script_notification_map_t::const_iterator it = mNotifications.find(notification_id); + if(mNotifications.end() != it) + { + return it->second; + } + return LLUUID::null; +} + +LLUUID LLScriptFloaterManager::findNotificationId(const LLUUID& object_id) +{ + if(object_id.notNull()) + { + script_notification_map_t::const_iterator it = findUsingObjectId(object_id); + if(mNotifications.end() != it) + { + return it->first; + } + } + return LLUUID::null; +} + +// static +LLScriptFloaterManager::EObjectType LLScriptFloaterManager::getObjectType(const LLUUID& notification_id) +{ + if(notification_id.isNull()) + { + LL_WARNS() << "Invalid notification ID" << LL_ENDL; + return OBJ_UNKNOWN; + } + + static const object_type_map TYPE_MAP = initObjectTypeMap(); + + LLNotificationPtr notification = LLNotificationsUtil::find(notification_id); + object_type_map::const_iterator it = TYPE_MAP.find(notification->getName()); + if(it != TYPE_MAP.end()) + { + return it->second; + } + + LL_WARNS() << "Unknown object type" << LL_ENDL; + return OBJ_UNKNOWN; +} + +// static +std::string LLScriptFloaterManager::getObjectName(const LLUUID& notification_id) +{ + using namespace LLNotificationsUI; + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(!notification) + { + LL_WARNS() << "Invalid notification" << LL_ENDL; + return LLStringUtil::null; + } + + std::string text; + + switch(LLScriptFloaterManager::getObjectType(notification_id)) + { + case LLScriptFloaterManager::OBJ_SCRIPT: + text = notification->getSubstitutions()["TITLE"].asString(); + break; + case LLScriptFloaterManager::OBJ_LOAD_URL: + text = notification->getSubstitutions()["OBJECTNAME"].asString(); + break; + case LLScriptFloaterManager::OBJ_GIVE_INVENTORY: + text = notification->getSubstitutions()["OBJECTFROMNAME"].asString(); + break; + default: + text = LLTrans::getString("object"); + break; + } + + return text; +} + +//static +LLScriptFloaterManager::object_type_map LLScriptFloaterManager::initObjectTypeMap() +{ + object_type_map type_map; + type_map["ScriptDialog"] = OBJ_SCRIPT; + type_map["ScriptDialogGroup"] = OBJ_SCRIPT; + type_map["LoadWebPage"] = OBJ_LOAD_URL; + type_map["ObjectGiveItem"] = OBJ_GIVE_INVENTORY; + return type_map; +} + +LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloaterManager::findUsingObjectId(const LLUUID& object_id) +{ + script_notification_map_t::const_iterator it = mNotifications.begin(); + for(; mNotifications.end() != it; ++it) + { + if(object_id == it->second) + { + return it; + } + } + return mNotifications.end(); +} + +LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloaterManager::findUsingObjectIdAndChannel(const LLUUID& object_id, S32 im_channel) +{ + script_notification_map_t::const_iterator it = mNotifications.begin(); + for (; mNotifications.end() != it; ++it) + { + if (object_id == it->second) + { + LLNotificationPtr notification = LLNotifications::instance().find(it->first); + if (notification && (im_channel == notification->getPayload()["chat_channel"].asInteger())) + { + return it; + } + } + } + return mNotifications.end(); +} + +void LLScriptFloaterManager::saveFloaterPosition(const LLUUID& object_id, const FloaterPositionInfo& fpi) +{ + if(object_id.notNull()) + { + LLScriptFloaterManager::getInstance()->mFloaterPositions[object_id] = fpi; + } + else + { + LL_WARNS() << "Invalid object id" << LL_ENDL; + } +} + +bool LLScriptFloaterManager::getFloaterPosition(const LLUUID& object_id, FloaterPositionInfo& fpi) +{ + floater_position_map_t::const_iterator it = mFloaterPositions.find(object_id); + if(LLScriptFloaterManager::getInstance()->mFloaterPositions.end() != it) + { + fpi = it->second; + return true; + } + return false; +} + +void LLScriptFloaterManager::setFloaterVisible(const LLUUID& notification_id, bool visible) +{ + LLScriptFloater* floater = LLFloaterReg::findTypedInstance( + "script_floater", notification_id); + if(floater) + { + floater->setVisible(visible); + } +} + +//static +void LLScriptFloaterManager::clearScriptNotifications() +{ + LLScriptFloaterManager* inst = LLScriptFloaterManager::getInstance(); + static const object_type_map TYPE_MAP = initObjectTypeMap(); + + script_notification_map_t::const_iterator ntf_it = inst->mNotifications.begin(); + while (inst->mNotifications.end() != ntf_it) + { + LLUUID notification_id = ntf_it->first; + ntf_it++; // onRemoveNotification() erases notification + LLNotificationPtr notification = LLNotifications::instance().find(notification_id); + if (notification) + { + object_type_map::const_iterator map_it = TYPE_MAP.find(notification->getName()); + if (map_it != TYPE_MAP.end() && map_it->second == OBJ_SCRIPT) + { + if (notification != NULL && !notification->isCancelled()) + { + LLNotificationsUtil::cancel(notification); + } + inst->onRemoveNotification(notification_id); + } + } + } +} + +////////////////////////////////////////////////////////////////// + +bool LLScriptFloater::isScriptTextbox(LLNotificationPtr notification) +{ + // get a form for the notification + LLNotificationFormPtr form(notification->getForm()); + + if (form) + { + // get number of elements in the form + int num_options = form->getNumElements(); + + // if ANY of the buttons have the magic lltextbox string as + // name, then treat the whole dialog as a simple text entry + // box (i.e. mixed button and textbox forms are not supported) + for (int i=0; igetElement(i); + if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) + { + return true; + } + } + } + + return false; +} + +// EOF -- cgit v1.2.3