diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
---|---|---|
committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llscriptfloater.cpp | |
parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (diff) |
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts:
# autobuild.xml
# indra/cmake/CMakeLists.txt
# indra/cmake/GoogleMock.cmake
# indra/llaudio/llaudioengine_fmodstudio.cpp
# indra/llaudio/llaudioengine_fmodstudio.h
# indra/llaudio/lllistener_fmodstudio.cpp
# indra/llaudio/lllistener_fmodstudio.h
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/llaudio/llstreamingaudio_fmodstudio.h
# indra/llcharacter/llmultigesture.cpp
# indra/llcharacter/llmultigesture.h
# indra/llimage/llimage.cpp
# indra/llimage/llimagepng.cpp
# indra/llimage/llimageworker.cpp
# indra/llimage/tests/llimageworker_test.cpp
# indra/llmessage/tests/llmockhttpclient.h
# indra/llprimitive/llgltfmaterial.h
# indra/llrender/llfontfreetype.cpp
# indra/llui/llcombobox.cpp
# indra/llui/llfolderview.cpp
# indra/llui/llfolderviewmodel.h
# indra/llui/lllineeditor.cpp
# indra/llui/lllineeditor.h
# indra/llui/lltextbase.cpp
# indra/llui/lltextbase.h
# indra/llui/lltexteditor.cpp
# indra/llui/lltextvalidate.cpp
# indra/llui/lltextvalidate.h
# indra/llui/lluictrl.h
# indra/llui/llview.cpp
# indra/llwindow/llwindowmacosx.cpp
# indra/newview/app_settings/settings.xml
# indra/newview/llappearancemgr.cpp
# indra/newview/llappearancemgr.h
# indra/newview/llavatarpropertiesprocessor.cpp
# indra/newview/llavatarpropertiesprocessor.h
# indra/newview/llbreadcrumbview.cpp
# indra/newview/llbreadcrumbview.h
# indra/newview/llbreastmotion.cpp
# indra/newview/llbreastmotion.h
# indra/newview/llconversationmodel.h
# indra/newview/lldensityctrl.cpp
# indra/newview/lldensityctrl.h
# indra/newview/llface.inl
# indra/newview/llfloatereditsky.cpp
# indra/newview/llfloatereditwater.cpp
# indra/newview/llfloateremojipicker.h
# indra/newview/llfloaterimsessiontab.cpp
# indra/newview/llfloaterprofiletexture.cpp
# indra/newview/llfloaterprofiletexture.h
# indra/newview/llgesturemgr.cpp
# indra/newview/llgesturemgr.h
# indra/newview/llimpanel.cpp
# indra/newview/llimpanel.h
# indra/newview/llinventorybridge.cpp
# indra/newview/llinventorybridge.h
# indra/newview/llinventoryclipboard.cpp
# indra/newview/llinventoryclipboard.h
# indra/newview/llinventoryfunctions.cpp
# indra/newview/llinventoryfunctions.h
# indra/newview/llinventorygallery.cpp
# indra/newview/lllistbrowser.cpp
# indra/newview/lllistbrowser.h
# indra/newview/llpanelobjectinventory.cpp
# indra/newview/llpanelprofile.cpp
# indra/newview/llpanelprofile.h
# indra/newview/llpreviewgesture.cpp
# indra/newview/llsavedsettingsglue.cpp
# indra/newview/llsavedsettingsglue.h
# indra/newview/lltooldraganddrop.cpp
# indra/newview/llurllineeditorctrl.cpp
# indra/newview/llvectorperfoptions.cpp
# indra/newview/llvectorperfoptions.h
# indra/newview/llviewerparceloverlay.cpp
# indra/newview/llviewertexlayer.cpp
# indra/newview/llviewertexturelist.cpp
# indra/newview/macmain.h
# indra/test/test.cpp
Diffstat (limited to 'indra/newview/llscriptfloater.cpp')
-rw-r--r-- | indra/newview/llscriptfloater.cpp | 1556 |
1 files changed, 778 insertions, 778 deletions
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index d714017e01..64e4502563 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<LLScriptFloater>("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<LLScriptFloater>("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<LLScriptFloater>("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<LLIMChiclet>(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<LLIMChiclet>(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<LLChiclet>(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<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - // 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<LLControlVariable> 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<U32> 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<LLIMChiclet>(old_id); - if (NULL != chicletp) - { - // Pass the new_message icon state further. - set_new_message = chicletp->getShowNewMessagesIcon(); - chicletp->hidePopupMenu(); - } - } - - LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("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<LLInvOfferChiclet>(notification_id); - } - else - { - chiclet_panelp->createChiclet<LLScriptChiclet>(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<LLScriptFloater>("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<LLScriptFloater>( - "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; i<num_options; ++i) - { - LLSD form_element = form->getElement(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<LLScriptFloater>("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<LLScriptFloater>("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<LLScriptFloater>("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<LLIMChiclet>(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<LLIMChiclet>(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<LLChiclet>(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<LLScreenChannel*>(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<LLControlVariable> 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<U32> 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<LLIMChiclet>(old_id);
+ if (NULL != chicletp)
+ {
+ // Pass the new_message icon state further.
+ set_new_message = chicletp->getShowNewMessagesIcon();
+ chicletp->hidePopupMenu();
+ }
+ }
+
+ LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("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<LLInvOfferChiclet>(notification_id);
+ }
+ else
+ {
+ chiclet_panelp->createChiclet<LLScriptChiclet>(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<LLScriptFloater>("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<LLScriptFloater>(
+ "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; i<num_options; ++i)
+ {
+ LLSD form_element = form->getElement(i);
+ if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// EOF
|