diff options
Diffstat (limited to 'indra/newview/llscriptfloater.cpp')
-rw-r--r-- | indra/newview/llscriptfloater.cpp | 390 |
1 files changed, 252 insertions, 138 deletions
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index cf62d47362..d452ef2228 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -38,9 +38,11 @@ #include "llchiclet.h" #include "llfloaterreg.h" #include "llnotifications.h" +#include "llnotificationsutil.h" #include "llscreenchannel.h" #include "llsyswellwindow.h" #include "lltoastnotifypanel.h" +#include "lltrans.h" #include "llviewerwindow.h" #include "llimfloater.h" @@ -65,14 +67,14 @@ LLUUID notification_id_to_object_id(const LLUUID& notification_id) LLScriptFloater::LLScriptFloater(const LLSD& key) : LLDockableFloater(NULL, true, key) , mScriptForm(NULL) +, mSaveFloaterPosition(false) { setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); setOverlapsScreenChannel(true); } -bool LLScriptFloater::toggle(const LLUUID& object_id) +bool LLScriptFloater::toggle(const LLUUID& notification_id) { - LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id); LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", notification_id); // show existing floater @@ -87,50 +89,52 @@ bool LLScriptFloater::toggle(const LLUUID& object_id) { floater->setVisible(TRUE); floater->setFocus(TRUE); - return true; } } // create and show new floater else { - show(object_id); - return true; + show(notification_id); } + + LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(notification_id, true); + return true; } -LLScriptFloater* LLScriptFloater::show(const LLUUID& object_id) +LLScriptFloater* LLScriptFloater::show(const LLUUID& notification_id) { - LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id); - - LLScriptFloater* floater = LLFloaterReg::showTypedInstance<LLScriptFloater>("script_floater", notification_id); - floater->setObjectId(object_id); - floater->createForm(object_id); + LLScriptFloater* floater = LLFloaterReg::getTypedInstance<LLScriptFloater>("script_floater", notification_id); + floater->setNotificationId(notification_id); + floater->createForm(notification_id); - if (floater->getDockControl() == NULL) + if(LLScriptFloaterManager::OBJ_SCRIPT == LLScriptFloaterManager::getObjectType(notification_id)) { - LLChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(object_id); - if (chiclet == NULL) - { - llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); - } - else - { - LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); - } - - floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), - LLDockControl::TOP, boost::bind(&LLScriptFloater::getAllowedRect, floater, _1))); + floater->setSavePosition(true); + floater->restorePosition(); + } + else + { + floater->dockToChiclet(true); } + LLFloaterReg::showTypedInstance<LLScriptFloater>("script_floater", notification_id, TRUE); + 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->getWorldViewRectRaw(); } -void LLScriptFloater::createForm(const LLUUID& object_id) +void LLScriptFloater::createForm(const LLUUID& notification_id) { // delete old form if(mScriptForm) @@ -139,8 +143,7 @@ void LLScriptFloater::createForm(const LLUUID& object_id) mScriptForm->die(); } - LLNotificationPtr notification = LLNotifications::getInstance()->find( - LLScriptFloaterManager::getInstance()->findNotificationId(object_id)); + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); if(NULL == notification) { return; @@ -162,9 +165,11 @@ void LLScriptFloater::createForm(const LLUUID& object_id) void LLScriptFloater::onClose(bool app_quitting) { - if(getObjectId().notNull()) + savePosition(); + + if(getNotificationId().notNull()) { - LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(getObjectId()); + LLScriptFloaterManager::getInstance()->onRemoveNotification(getNotificationId()); } } @@ -172,6 +177,8 @@ void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) { LLDockableFloater::setDocked(docked, pop_on_undock); + savePosition(); + hideToastsIfNeeded(); } @@ -180,14 +187,23 @@ 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(getObjectId().notNull()) + if(getNotificationId().notNull()) { // Remove new message icon - LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getObjectId()); + LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getNotificationId()); if (chiclet == NULL) { llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); @@ -199,6 +215,77 @@ void LLScriptFloater::onMouseDown() } } +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)), dock); + + // Restore saving + setSavePosition(save); + } +} + void LLScriptFloater::hideToastsIfNeeded() { using namespace LLNotificationsUI; @@ -220,200 +307,227 @@ void LLScriptFloater::hideToastsIfNeeded() void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) { - // get scripted Object's ID - LLUUID object_id = notification_id_to_object_id(notification_id); - if(object_id.isNull()) + if(notification_id.isNull()) { - llwarns << "Invalid notification, no object id" << llendl; + 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); - // If an Object spawns more-than-one floater, only the newest one is shown. - // The previous is automatically closed. - script_notification_map_t::iterator it = mNotifications.find(object_id); - if(it != mNotifications.end()) + // LLDialog can spawn only one instance, LLLoadURL and LLGiveInventory can spawn unlimited number of instances + if(OBJ_SCRIPT == obj_type) { - LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id); - if(chiclet) + // 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()) { - // Pass the new_message icon state further. - set_new_message = chiclet->getShowNewMessagesIcon(); - } + 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->second.notification_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(); - } + 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(); + } - onRemoveNotification(it->second.notification_id); + onRemoveNotification(it->first); + } } - LLNotificationData nd = {notification_id}; - mNotifications.insert(std::make_pair(object_id, nd)); + mNotifications.insert(std::make_pair(notification_id, object_id)); // Create inventory offer chiclet for offer type notifications - LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); - if( notification && notification->getType() == "offer" ) + if( OBJ_GIVE_INVENTORY == obj_type ) { - LLBottomTray::instance().getChicletPanel()->createChiclet<LLInvOfferChiclet>(object_id); + LLBottomTray::instance().getChicletPanel()->createChiclet<LLInvOfferChiclet>(notification_id); } else { - LLBottomTray::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(object_id); + LLBottomTray::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(notification_id); } - LLIMWellWindow::getInstance()->addObjectRow(object_id, set_new_message); + LLIMWellWindow::getInstance()->addObjectRow(notification_id, set_new_message); LLSD data; - data["object_id"] = object_id; + data["notification_id"] = notification_id; data["new_message"] = set_new_message; data["unread"] = 1; // each object has got only one floater mNewObjectSignal(data); - toggleScriptFloater(object_id, set_new_message); + toggleScriptFloater(notification_id, set_new_message); } void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) { - LLUUID object_id = findObjectId(notification_id); - if(object_id.isNull()) + if(notification_id.isNull()) { - llwarns << "Invalid notification, no object id" << llendl; + llwarns << "Invalid notification ID" << llendl; return; } - using namespace LLNotificationsUI; - - // remove related toast - LLUUID channel_id(gSavedSettings.getString("NotificationChannelUUID")); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*> - (LLChannelManager::getInstance()->findChannelByID(channel_id)); - LLUUID n_toast_id = findNotificationToastId(object_id); - if(channel && n_toast_id.notNull()) - { - channel->killToastByNotificationID(n_toast_id); - } - // remove related chiclet - LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(object_id); + LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(notification_id); - LLIMWellWindow::getInstance()->removeObjectRow(object_id); + LLIMWellWindow::getInstance()->removeObjectRow(notification_id); // close floater LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", notification_id); if(floater) { - floater->setObjectId(LLUUID::null); + floater->savePosition(); + floater->setNotificationId(LLUUID::null); floater->closeFloater(); } - mNotifications.erase(object_id); + mNotifications.erase(notification_id); } -void LLScriptFloaterManager::removeNotificationByObjectId(const LLUUID& object_id) +void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& notification_id, bool set_new_message) { - // Check we have not removed notification yet - LLNotificationPtr notification = LLNotifications::getInstance()->find( - findNotificationId(object_id)); - if(notification) - { - onRemoveNotification(notification->getID()); - } -} - -void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool set_new_message) -{ - // kill toast - using namespace LLNotificationsUI; - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - if(channel) - { - channel->killToastByNotificationID(findNotificationToastId(object_id)); - } - LLSD data; - data["object_id"] = object_id; + data["notification_id"] = notification_id; data["new_message"] = set_new_message; mToggleFloaterSignal(data); // toggle floater - LLScriptFloater::toggle(object_id); + LLScriptFloater::toggle(notification_id); } -void LLScriptFloaterManager::setNotificationToastId(const LLUUID& object_id, const LLUUID& notification_id) +LLUUID LLScriptFloaterManager::findObjectId(const LLUUID& notification_id) { - script_notification_map_t::iterator it = mNotifications.find(object_id); + script_notification_map_t::const_iterator it = mNotifications.find(notification_id); if(mNotifications.end() != it) { - it->second.toast_notification_id = notification_id; + return it->second; } + return LLUUID::null; } -LLUUID LLScriptFloaterManager::findObjectId(const LLUUID& notification_id) +LLUUID LLScriptFloaterManager::findNotificationId(const LLUUID& object_id) { - if(notification_id.notNull()) + if(object_id.notNull()) { - script_notification_map_t::const_iterator it = mNotifications.begin(); - for(; mNotifications.end() != it; ++it) + script_notification_map_t::const_iterator it = findUsingObjectId(object_id); + if(mNotifications.end() != it) { - if(notification_id == it->second.notification_id) - { - return it->first; - } + return it->first; } } return LLUUID::null; } -LLUUID LLScriptFloaterManager::findNotificationId(const LLUUID& object_id) +// static +LLScriptFloaterManager::EObjectType LLScriptFloaterManager::getObjectType(const LLUUID& notification_id) { - script_notification_map_t::const_iterator it = mNotifications.find(object_id); - if(mNotifications.end() != it) + if(notification_id.isNull()) { - return it->second.notification_id; + llwarns << "Invalid notification ID" << llendl; + return OBJ_UNKNOWN; } - return LLUUID::null; -} -LLUUID LLScriptFloaterManager::findNotificationToastId(const LLUUID& object_id) -{ - script_notification_map_t::const_iterator it = mNotifications.find(object_id); - if(mNotifications.end() != it) + 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.toast_notification_id; + return it->second; } - return LLUUID::null; + + llwarns << "Unknown object type" << llendl; + return OBJ_UNKNOWN; } -//static -void LLScriptFloaterManager::onToastButtonClick(const LLSD¬ification, const LLSD&response) +// static +std::string LLScriptFloaterManager::getObjectName(const LLUUID& notification_id) { - S32 option = LLNotification::getSelectedOption(notification, response); - LLUUID object_id = notification["payload"]["object_id"].asUUID(); + using namespace LLNotificationsUI; + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(!notification) + { + llwarns << "Invalid notification" << llendl; + return LLStringUtil::null; + } - switch(option) + std::string text; + + switch(LLScriptFloaterManager::getObjectType(notification_id)) { - case 0: // "Open" - LLScriptFloaterManager::getInstance()->toggleScriptFloater(object_id); + case LLScriptFloaterManager::OBJ_SCRIPT: + text = notification->getSubstitutions()["TITLE"].asString(); break; - case 1: // "Ignore" - LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id); + case LLScriptFloaterManager::OBJ_LOAD_URL: + text = notification->getSubstitutions()["OBJECTNAME"].asString(); break; - case 2: // "Block" - LLMuteList::getInstance()->add(LLMute(object_id, notification["substitutions"]["TITLE"], LLMute::OBJECT)); - LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id); + case LLScriptFloaterManager::OBJ_GIVE_INVENTORY: + text = notification->getSubstitutions()["NAME"].asString(); break; default: - llwarns << "Unexpected value" << llendl; + 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; } // EOF |