summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llnotificationmanager.cpp4
-rw-r--r--indra/newview/llnotificationscripthandler.cpp2
-rw-r--r--indra/newview/llscriptfloater.cpp17
-rw-r--r--indra/newview/llscripttextboxfloater.cpp576
-rw-r--r--indra/newview/llscripttextboxfloater.h212
5 files changed, 805 insertions, 6 deletions
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index cd0d323741..3967117fc8 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -73,8 +73,8 @@ void LLNotificationManager::init()
LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1));
LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1));
- //mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));
- mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptTextboxHandler(NT_NOTIFY, LLSD()));
+ mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));
+ //mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptTextboxHandler(NT_NOTIFY, LLSD()));
mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD()));
mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD()));
mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD()));
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 45590c3cdb..eed0bdc15d 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -97,10 +97,12 @@ bool LLScriptHandler::processNotification(const LLSD& notify)
if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName())
{
+ llwarns << "DUMB ROUTE" << llendl;
LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());
}
else
{
+ llwarns << "SMART ROUTE" << llendl;
LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
LLToast::Params p;
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 2334f0cde5..0f7223aaf0 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -37,6 +37,7 @@
#include "llscreenchannel.h"
#include "llsyswellwindow.h"
#include "lltoastnotifypanel.h"
+#include "lltoastscripttextbox.h"
#include "lltrans.h"
#include "llviewerwindow.h"
#include "llimfloater.h"
@@ -151,10 +152,18 @@ void LLScriptFloater::createForm(const LLUUID& notification_id)
// create new form
LLRect toast_rect = getRect();
- // 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);
+ if (isScriptTextBox())
+ {
+ mScriptForm = new LLToastScriptTextbox(notify, toast_rect);
+ }
+ 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
diff --git a/indra/newview/llscripttextboxfloater.cpp b/indra/newview/llscripttextboxfloater.cpp
new file mode 100644
index 0000000000..0f7223aaf0
--- /dev/null
+++ b/indra/newview/llscripttextboxfloater.cpp
@@ -0,0 +1,576 @@
+/**
+ * @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 "llbottomtray.h"
+#include "llchannelmanager.h"
+#include "llchiclet.h"
+#include "llfloaterreg.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llscreenchannel.h"
+#include "llsyswellwindow.h"
+#include "lltoastnotifypanel.h"
+#include "lltoastscripttextbox.h"
+#include "lltrans.h"
+#include "llviewerwindow.h"
+#include "llimfloater.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);
+ }
+
+ LLBottomTray::getInstance()->getChicletPanel()->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::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectScaled();
+}
+
+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())
+ {
+ mScriptForm = new LLToastScriptTextbox(notify, toast_rect);
+ }
+ 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)
+ {
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getNotificationId());
+ if(chiclet)
+ {
+ chiclet->setToggleState(false);
+ }
+ }
+}
+
+void LLScriptFloater::onMouseDown()
+{
+ if(getNotificationId().notNull())
+ {
+ // Remove new message icon
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getNotificationId());
+ if (chiclet == NULL)
+ {
+ llerror("Dock chiclet for LLScriptFloater doesn't exist", 0);
+ }
+ else
+ {
+ chiclet->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())
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(getNotificationId(), false);
+ }
+}
+
+void LLScriptFloater::onFocusReceived()
+{
+ // first focus will be received before setObjectId() call - don't toggle chiclet
+ if(getNotificationId().notNull())
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(getNotificationId(), true);
+ }
+}
+
+void LLScriptFloater::dockToChiclet(bool dock)
+{
+ if (getDockControl() == NULL)
+ {
+ LLChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(getNotificationId());
+ if (chiclet == NULL)
+ {
+ llwarns << "Dock chiclet for LLScriptFloater doesn't exist" << llendl;
+ return;
+ }
+ else
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet);
+ }
+
+ // Stop saving position while we dock floater
+ bool save = getSavePosition();
+ setSavePosition(false);
+
+ setDockControl(new LLDockControl(chiclet, this, getDockTongue(),
+ LLDockControl::TOP, boost::bind(&LLScriptFloater::getAllowedRect, this, _1)));
+
+ 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();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
+{
+ if(notification_id.isNull())
+ {
+ llwarns << "Invalid notification ID" << llendl;
+ return;
+ }
+
+ // 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)
+ {
+ // If an Object spawns more-than-one floater, only the newest one is shown.
+ // The previous is automatically closed.
+ script_notification_map_t::const_iterator it = findUsingObjectId(object_id);
+ if(it != mNotifications.end())
+ {
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(it->first);
+ if(chiclet)
+ {
+ // Pass the new_message icon state further.
+ set_new_message = chiclet->getShowNewMessagesIcon();
+ }
+
+ LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first);
+ 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(it->first);
+ }
+ }
+
+ mNotifications.insert(std::make_pair(notification_id, object_id));
+
+ // Create inventory offer chiclet for offer type notifications
+ if( OBJ_GIVE_INVENTORY == obj_type )
+ {
+ LLBottomTray::instance().getChicletPanel()->createChiclet<LLInvOfferChiclet>(notification_id);
+ }
+ else
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->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())
+ {
+ llwarns << "Invalid notification ID" << llendl;
+ return;
+ }
+
+ // remove related chiclet
+ LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(notification_id);
+
+ LLIMWellWindow::getInstance()->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())
+ {
+ llwarns << "Invalid notification ID" << llendl;
+ 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;
+ }
+
+ llwarns << "Unknown object type" << llendl;
+ return OBJ_UNKNOWN;
+}
+
+// static
+std::string LLScriptFloaterManager::getObjectName(const LLUUID& notification_id)
+{
+ using namespace LLNotificationsUI;
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if(!notification)
+ {
+ llwarns << "Invalid notification" << llendl;
+ 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();
+}
+
+void LLScriptFloaterManager::saveFloaterPosition(const LLUUID& object_id, const FloaterPositionInfo& fpi)
+{
+ if(object_id.notNull())
+ {
+ LLScriptFloaterManager::getInstance()->mFloaterPositions[object_id] = fpi;
+ }
+ else
+ {
+ llwarns << "Invalid object id" << llendl;
+ }
+}
+
+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);
+ }
+}
+
+// EOF
diff --git a/indra/newview/llscripttextboxfloater.h b/indra/newview/llscripttextboxfloater.h
new file mode 100644
index 0000000000..b0ab725810
--- /dev/null
+++ b/indra/newview/llscripttextboxfloater.h
@@ -0,0 +1,212 @@
+/**
+ * @file llscripttextboxfloater.h
+ * @brief LLScriptTextboxFloater 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$
+ */
+
+#ifndef LL_SCRIPTTEXTBOXFLOATER_H
+#define LL_SCRIPTTEXTBOXFLOATER_H
+
+#include "lltransientdockablefloater.h"
+
+class LLToastNotifyPanel;
+
+/**
+ * Handles script notifications ("ScriptDialog" and "ScriptDialogGroup")
+ * and manages Script Floaters.
+ */
+class LLScriptTextboxFloaterManager : public LLSingleton<LLScriptTextboxFloaterManager>
+{
+ // *TODO
+ // LLScriptTextboxFloaterManager and LLScriptTextboxFloater will need some refactoring after we
+ // know how script notifications should look like.
+public:
+
+ typedef enum e_object_type
+ {
+ OBJ_SCRIPT,
+ OBJ_GIVE_INVENTORY,
+ OBJ_LOAD_URL,
+
+ OBJ_UNKNOWN
+ }EObjectType;
+
+ /**
+ * Handles new notifications.
+ * Saves notification and object ids, removes old notification if needed, creates script chiclet
+ * Note that one object can spawn one script floater.
+ */
+ void onAddNotification(const LLUUID& notification_id);
+
+ /**
+ * Removes notification.
+ */
+ void removeNotification(const LLUUID& notification_id);
+
+ /**
+ * Handles notification removal.
+ * Removes script notification toast, removes script chiclet, closes script floater
+ */
+ void onRemoveNotification(const LLUUID& notification_id);
+
+ /**
+ * Toggles script floater.
+ * Removes "new message" icon from chiclet and removes notification toast.
+ */
+ void toggleScriptFloater(const LLUUID& object_id, bool set_new_message = false);
+
+ LLUUID findObjectId(const LLUUID& notification_id);
+
+ LLUUID findNotificationId(const LLUUID& object_id);
+
+ static EObjectType getObjectType(const LLUUID& notification_id);
+
+ static std::string getObjectName(const LLUUID& notification_id);
+
+ typedef boost::signals2::signal<void(const LLSD&)> object_signal_t;
+
+ boost::signals2::connection addNewObjectCallback(const object_signal_t::slot_type& cb) { return mNewObjectSignal.connect(cb); }
+ boost::signals2::connection addToggleObjectFloaterCallback(const object_signal_t::slot_type& cb) { return mToggleFloaterSignal.connect(cb); }
+
+ struct FloaterPositionInfo
+ {
+ LLRect mRect;
+ bool mDockState;
+ };
+
+ void saveFloaterPosition(const LLUUID& object_id, const FloaterPositionInfo& fpi);
+
+ bool getFloaterPosition(const LLUUID& object_id, FloaterPositionInfo& fpi);
+
+ void setFloaterVisible(const LLUUID& notification_id, bool visible);
+
+protected:
+
+ typedef std::map<std::string, EObjectType> object_type_map;
+
+ static object_type_map initObjectTypeMap();
+
+ // <notification_id, object_id>
+ typedef std::map<LLUUID, LLUUID> script_notification_map_t;
+
+ script_notification_map_t::const_iterator findUsingObjectId(const LLUUID& object_id);
+
+private:
+
+ script_notification_map_t mNotifications;
+
+ object_signal_t mNewObjectSignal;
+ object_signal_t mToggleFloaterSignal;
+
+ // <object_id, floater position>
+ typedef std::map<LLUUID, FloaterPositionInfo> floater_position_map_t;
+
+ floater_position_map_t mFloaterPositions;
+};
+
+/**
+ * Floater script forms.
+ * LLScriptTextboxFloater will create script form based on notification data and
+ * will auto fit the form.
+ */
+class LLScriptTextboxFloater : public LLDockableFloater
+{
+public:
+
+ /**
+ * key - UUID of scripted Object
+ */
+ LLScriptTextboxFloater(const LLSD& key);
+
+ virtual ~LLScriptTextboxFloater(){};
+
+ /**
+ * Toggle existing floater or create and show a new one.
+ */
+ static bool toggle(const LLUUID& object_id);
+
+ /**
+ * Creates and shows floater
+ */
+ static LLScriptTextboxFloater* show(const LLUUID& object_id);
+
+ const LLUUID& getNotificationId() { return mNotificationId; }
+
+ void setNotificationId(const LLUUID& id);
+
+ /**
+ * Close notification if script floater is closed.
+ */
+ /*virtual*/ void onClose(bool app_quitting);
+
+ /**
+ * Hide all notification toasts when we show dockable floater
+ */
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+
+ /**
+ * Hide all notification toasts when we show dockable floater
+ */
+ /*virtual*/ void setVisible(BOOL visible);
+
+ bool getSavePosition() { return mSaveFloaterPosition; }
+
+ void setSavePosition(bool save) { mSaveFloaterPosition = save; }
+
+ void savePosition();
+
+ void restorePosition();
+
+protected:
+
+ /**
+ * Creates script form, will delete old form if floater is shown for same object.
+ */
+ void createForm(const LLUUID& object_id);
+
+ /*virtual*/ void getAllowedRect(LLRect& rect);
+
+ /**
+ * Hide all notification toasts.
+ */
+ static void hideToastsIfNeeded();
+
+ /**
+ * Removes chiclets new messages icon
+ */
+ void onMouseDown();
+
+ /*virtual*/ void onFocusLost();
+
+ /*virtual*/ void onFocusReceived();
+
+ void dockToChiclet(bool dock);
+
+private:
+ LLToastNotifyPanel* mScriptForm;
+ LLUUID mNotificationId;
+ LLUUID mObjectId;
+ bool mSaveFloaterPosition;
+};
+
+#endif //LL_SCRIPTFLOATER_H