//static bool LLNotifyBox::onNotification(const LLSD& notify) { LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if (!notification) return false; if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { //bring existing notification to top LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { gNotifyBoxView->showOnly(boxp); } else { bool is_script_dialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); LLNotifyBox* notify_box = new LLNotifyBox( notification, is_script_dialog); //layout_script_dialog); gNotifyBoxView->addChild(notify_box); } } else if (notify["sigtype"].asString() == "delete") { LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { boxp->close(); } } return false; }
//-------------------------------------------------------------------------- bool LLIMHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { LLSD substitutions = notification->getSubstitutions(); // According to comments in LLIMMgr::addMessage(), if we get message // from ourselves, the sender id is set to null. This fixes EXT-875. LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); if (avatar_id.isNull()) avatar_id = gAgentID; LLToastIMPanel::Params im_p; im_p.notification = notification; im_p.avatar_id = avatar_id; im_p.from = substitutions["FROM"].asString(); im_p.time = substitutions["TIME"].asString(); im_p.message = substitutions["MESSAGE"].asString(); im_p.session_id = substitutions["SESSION_ID"].asUUID(); LLToastIMPanel* im_box = new LLToastIMPanel(im_p); LLToast::Params p; p.notif_id = notification->getID(); p.session_id = im_p.session_id; p.notification = notification; p.panel = im_box; p.can_be_stored = false; p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); // send a signal to the counter manager; mNewNotificationSignal(); } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); } return false; }
// static void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification) { const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; LLUUID session_id = spawnIMSession(name, from_id); // add offer to session LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( session_id); llassert_always(session != NULL); LLSD offer; offer["notification_id"] = notification->getID(); offer["from"] = SYSTEM_FROM; offer["time"] = LLLogChat::timestamp(false); offer["index"] = (LLSD::Integer)session->mMsgs.size(); session->mMsgs.push_front(offer); // update IM floater and counters LLSD arg; arg["session_id"] = session_id; arg["num_unread"] = ++(session->mNumUnread); arg["participant_unread"] = ++(session->mParticipantUnreadMessageCount); LLIMModel::getInstance()->mNewMsgSignal(arg); }
void LLAlertHandler::onChange( LLNotificationPtr notification ) { LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); }
//-------------------------------------------------------------------------- void LLOfferHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); // if (notification // && LLNotificationManager::getInstance()->getHandlerForNotification( // notification->getType()) == this // // don't delete notification since it may be used by IM floater // && !LLHandlerUtil::canAddNotifPanelToIM(notification)) // { // LLNotifications::instance().cancel(notification); // } // [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Modified: Catznip-2.5.0a // NOTE: this will be fired from LLScreenChannel::killToastByNotificationID() which treats visible and stored toasts differently if ( (notification) && (!notification->isCancelled()) && (LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) ) { LLScreenChannel* pChannel = dynamic_cast<LLScreenChannel*>(mChannel); LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification->getID()) : NULL; if ( (!pToast) || (pToast->getCanBeStored()) ) { LLNotifications::instance().cancel(notification); } } // [/SL:KB] }
//static bool LLAlertDialog::onNewNotification(const LLSD& notify, bool is_modal) { LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(notification) { if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") { LLAlertDialog* dialog = new LLAlertDialog(notification, is_modal); dialog->show(); } else if (notify["sigtype"].asString() == "change") { LLAlertDialog* dialog = getInstance(notification->getID()); if (dialog) { dialog->show(); } else { LLAlertDialog* dialog = new LLAlertDialog(notification, is_modal); dialog->show(); } } } return false; }
//-------------------------------------------------------------------------- bool LLAlertHandler::processNotification(const LLNotificationPtr& notification) { if(mChannel.isDead()) { return false; } // arrange a channel on a screen if(!mChannel.get()->getVisible()) { initChannel(); } if (notification->canLogToIM() && notification->hasFormElements()) { const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; // [RLVa:KB] - Checked: 2013-05-09 (RLVa-1.4.9) // Don't spawn an IM session for non-chat related events: // - LLHandlerUtil::logToIMP2P() below will still be called with to_file_only == false // - LLHandlerUtil::logToIM() will eventually be called as a result and without an open IM session it will log the // same message as it would for an open session whereas to_file_only == true would take a different code path if ( (RlvActions::hasOpenP2PSession(from_id)) || (RlvActions::canStartIM(from_id)) ) { // [/RLVa:KB] // firstly create session... LLHandlerUtil::spawnIMSession(name, from_id); // [RLVa:KB] - Checked: 2013-05-09 (RLVa-1.4.9) } // [/RLVa:KB] // ...then log message to have IM Well notified about new message LLHandlerUtil::logToIMP2P(notification); } LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); p.enable_hide_btn = false; p.can_fade = false; p.is_modal = mIsModal; p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); // Show alert in middle of progress view (during teleport) (EXT-1093) LLProgressView* progress = gViewerWindow->getProgressView(); LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); mChannel.get()->updatePositionAndSize(rc); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); return false; }
//-------------------------------------------------------------------------- bool LLGroupHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { LLHandlerUtil::logGroupNoticeToIMGroup(notification); LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); // send a signal to the counter manager mNewNotificationSignal(); LLGroupActions::refresh_notices(); } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); } return false; }
//static bool LLNotifyBox::onNotification(const LLSD& notify) { LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if (!notification) return false; if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { //bring existing notification to top //This getInstance is ugly, as LLNotifyBox is derived from both LLInstanceTracker and LLEventTimer, which also is derived from its own LLInstanceTracker //Have to explicitly determine which getInstance function to use. LLNotifyBox* boxp = LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { gNotifyBoxView->showOnly(boxp); } else { bool is_script_dialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); LLNotifyBox* notify_box = new LLNotifyBox( notification, is_script_dialog); //layout_script_dialog); gNotifyBoxView->addChild(notify_box); } } else if (notify["sigtype"].asString() == "delete") { LLNotifyBox* boxp = LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { boxp->close(); } } return false; }
//static bool LLNotifyBox::onNotification(const LLSD& notify) { LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if (!notification) return false; if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { if (notification->getPayload().has("SUPPRESS_TOAST")) { chat_notification(notification); return false; } //bring existing notification to top //This getInstance is ugly, as LLNotifyBox is derived from both LLInstanceTracker and LLEventTimer, which also is derived from its own LLInstanceTracker //Have to explicitly determine which getInstance function to use. LLNotifyBox* boxp = LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { gNotifyBoxView->showOnly(boxp); } else { gNotifyBoxView->addChild(new LLNotifyBox(notification)); } } else if (notify["sigtype"].asString() == "delete") { LLNotifyBox* boxp = LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { boxp->close(); } } return false; }
void LLScriptHandler::onDeleteToast(LLToast* toast) { // send a signal to the counter manager mDelNotificationSignal(); // send a signal to a listener to let him perform some action // in this case listener is a SysWellWindow and it will remove a corresponding item from its list mNotificationIDSignal(toast->getNotificationID()); LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); if( notification && (SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) ) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } }
LLAlertDialog::LLAlertDialog( LLNotificationPtr notification, bool modal) : LLModalDialog( notification->getLabel(), 100, 100, modal ), // dummy size. Will reshape below. LLInstanceTracker<LLAlertDialog, LLUUID>(notification->getID()), mDefaultButton( NULL ), mCheck(NULL), mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH), mLabel(notification->getName()), mLineEditor(NULL), mNote(notification) { const LLFontGL* font = LLResMgr::getInstance()->getRes( FONT_NAME ); const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); const S32 EDITOR_HEIGHT = 20; LLNotificationFormPtr form = mNote->getForm(); std::string edit_text_name; std::string edit_text_contents; bool is_password = false; setBackgroundVisible(TRUE); setBackgroundOpaque(TRUE); typedef std::list<ButtonData> options_t; options_t options; // for now, get LLSD to iterator over form elements LLSD form_sd = form->asLLSD(); for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it) { std::string type = (*it)["type"].asString(); if (type == "button") { options.push_back(ButtonData()); ButtonData& button_data = options.back(); button_data.mName = (*it)["name"].asString(); button_data.mText = (*it)["text"].asString(); button_data.mDefault = (*it)["default"].asBoolean(); if(options.size()-1 == mNote->getURLOption()) button_data.mUrl = mNote->getURL(); } else if (type == "text") { edit_text_contents = (*it)["value"].asString(); edit_text_name = (*it)["name"].asString(); } else if (type == "password") { edit_text_contents = (*it)["value"].asString(); edit_text_name = (*it)["name"].asString(); is_password = true; } } // Buttons if (options.empty()) { options.push_back(ButtonData()); ButtonData& button_data = options.back(); button_data.mName = "close"; button_data.mText = "Close"; button_data.mDefault = true; } S32 num_options = options.size(); // Calc total width of buttons S32 button_width = 0; S32 sp = font->getWidth(std::string("OO")); for( options_t::iterator it = options.begin(); it != options.end(); it++ ) { S32 w = S32(font->getWidth( it->mText ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD; button_width = llmax( w, button_width ); } S32 btn_total_width = button_width; if( num_options > 1 ) { btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD); } // Message: create text box using raw string, as text has been structure deliberately // Use size of created text box to generate dialog box size std::string msg = mNote->getMessage(); llwarns << "Alert: " << msg << llendl; LLTextBox* msg_box = new LLTextBox( std::string("Alert message"), msg, (F32)MAX_ALLOWED_MSG_WIDTH, font ); const LLRect& text_rect = msg_box->getRect(); S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD; S32 dialog_height = text_rect.getHeight() + 3 * VPAD + BTN_HEIGHT; if (hasTitleBar()) { dialog_height += LINE_HEIGHT; // room for title bar } // it's ok for the edit text body to be empty, but we want the name to exist if we're going to draw it if (!edit_text_name.empty()) { dialog_height += EDITOR_HEIGHT + VPAD; dialog_width = llmax(dialog_width, (S32)(font->getWidth( edit_text_contents ) + 0.99f)); } if (mCaution) { // Make room for the caution icon. dialog_width += 32 + HPAD; } reshape( dialog_width, dialog_height, FALSE ); S32 msg_y = getRect().getHeight() - VPAD; S32 msg_x = HPAD; if (hasTitleBar()) { msg_y -= LINE_HEIGHT; // room for title } if (mCaution) { LLIconCtrl* icon = new LLIconCtrl(std::string("icon"), LLRect(msg_x, msg_y, msg_x+32, msg_y-32), std::string("notify_caution_icon.tga")); icon->setMouseOpaque(FALSE); addChild(icon); msg_x += 32 + HPAD; msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertCautionTextColor" ) ); } else { msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) ); } LLRect rect; rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() ); msg_box->setRect( rect ); addChild(msg_box); // Buttons S32 button_left = (getRect().getWidth() - btn_total_width) / 2; for( options_t::iterator it = options.begin(); it != options.end(); it++ ) { LLRect button_rect; button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ); ButtonData& button_data = *it; LLButton* btn = new LLButton( button_data.mName, button_rect, "","", "", NULL, font, button_data.mText, button_data.mText); btn->setClickedCallback(boost::bind(&LLAlertDialog::onButtonPressed, this, _1, button_data.mUrl)); addChild(btn); if(!mDefaultButton || button_data.mDefault) { mDefaultButton = btn; } button_left += button_width + BTN_HPAD; } llassert(mDefaultButton); //'options' map should never be empty, thus mDefaultButton should always get set in the above loop. mDefaultButton->setFocus(TRUE); // (Optional) Edit Box if (!edit_text_name.empty()) { S32 y = VPAD + BTN_HEIGHT + VPAD/2; mLineEditor = new LLLineEditor(edit_text_name, LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y), edit_text_contents, LLFontGL::getFontSansSerif(), STD_STRING_STR_LEN); // make sure all edit keys get handled properly (DEV-22396) mLineEditor->setHandleEditKeysDirectly(TRUE); addChild(mLineEditor); } if (mLineEditor) { mLineEditor->setDrawAsterixes(is_password); setEditTextArgs(notification->getSubstitutions()); } std::string ignore_label; if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE) { setCheckBox(LLNotificationTemplates::instance().getGlobalString("skipnexttime"), ignore_label); } else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) { setCheckBox(LLNotificationTemplates::instance().getGlobalString("alwayschoose"), ignore_label); } }
LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLToastPanel(notification), LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID()) { init(rect, show_images); }
//-------------------------------------------------------------------------- bool LLAlertHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") { if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) { const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; // firstly create session... LLHandlerUtil::spawnIMSession(name, from_id); // ...then log message to have IM Well notified about new message LLHandlerUtil::logToIMP2P(notification); } LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); p.enable_hide_btn = false; p.can_fade = false; p.is_modal = mIsModal; p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); // Show alert in middle of progress view (during teleport) (EXT-1093) LLProgressView* progress = gViewerWindow->getProgressView(); LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); mChannel->updatePositionAndSize(rc); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); } else if (notify["sigtype"].asString() == "change") { LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } else { LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->killToastByNotificationID(notification->getID()); } return false; }
//-------------------------------------------------------------------------- bool LLTipHandler::processNotification(const LLSD& notify) { if(mChannel.isDead()) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel.get()->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { // archive message in nearby chat if (LLHandlerUtil::canLogToNearbyChat(notification)) { LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened LLFloaterNearbyChat* nearby_chat = LLFloaterNearbyChat::getInstance(); // <FS:Zi> Remove floating chat bar // LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); // if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) if (nearby_chat->getVisible()) // </FS:Zi> { return false; } } std::string session_name = notification->getPayload()["SESSION_NAME"]; const std::string name = notification->getSubstitutions()["NAME"]; const LLUUID agent_id = notification->getSubstitutions()["AGENT-ID"]; if (session_name.empty()) { session_name = name; } LLUUID from_id = notification->getPayload()["from_id"]; if (LLHandlerUtil::canLogToIM(notification)) { // LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, // notification->getMessage(), from_id, from_id); // [SL:KB] - Patch: Chat-Logs | Checked: 2010-11-18 (Catznip-2.4.0c) | Added: Catznip-2.4.0c LLHandlerUtil::logToIMP2P(notification, false); // [/SL:KB] } if (LLHandlerUtil::canSpawnIMSession(notification)) { LLHandlerUtil::spawnIMSession(name, from_id); } // don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) if (!LLHandlerUtil::canSpawnToast(notification)) { return false; } // [FIRE-3522 : SJ] Only show Online/Offline toast when ChatOnlineNotification is enabled or the Friend is one you want to have on/offline notices from if (!gSavedSettings.getBOOL("ChatOnlineNotification") && ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName())) { // [FIRE-3522 : SJ] Only show Online/Offline toast for groups which have enabled "Show notice for this set" and in the settingpage of CS is checked that the messages need to be in Toasts if (!(gSavedSettings.getBOOL("FSContactSetsNotificationToast") && LGGContactSets::getInstance()->notifyForFriend(agent_id))) { return false; } } LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); p.panel = notify_box; p.is_tip = true; p.can_be_stored = false; removeExclusiveNotifications(notification); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); } else if (notify["sigtype"].asString() == "delete") { mChannel.get()->killToastByNotificationID(notification->getID()); } return false; }
//-------------------------------------------------------------------------- bool LLIMHandler::processNotification(const LLSD& notify) { if(mChannel.isDead()) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; static LLCachedControl<bool> fsUseNearbyChatConsole(gSavedSettings, "FSUseNearbyChatConsole"); if (FSLogImToChatConsole && fsUseNearbyChatConsole) { if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { LLSD substitutions = notification->getSubstitutions(); // FS:LO FIRE-5230 - Chat Console Improvement: Replacing the "IM" in front of group chat messages with the actual group name std::string group; LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(substitutions["SESSION_ID"]); if(session) { S32 groupNameLength = gSavedSettings.getS32("FSShowGroupNameLength"); if(groupNameLength != 0 && session->isGroupSessionType()) { group = session->mName.substr(0,groupNameLength); } } // FS:LO FIRE-5230 - Chat Console Improvement: Replacing the "IM" in front of group chat messages with the actual group name // Filter notifications with empty ID and empty message if (substitutions["FROM_ID"].asString() == "" && substitutions["MESSAGE"].asString() == "") return false; // Ansarial, replace long lock of local DN handling with the following call //LLAvatarNameCache::get(LLUUID(substitutions["FROM_ID"].asString()), boost::bind(&LLIMHandler::onAvatarNameLookup, this, _1, _2, substitutions["MESSAGE"].asString())); LLAvatarNameCache::get(LLUUID(substitutions["FROM_ID"].asString()), boost::bind(&LLIMHandler::onAvatarNameLookup, this, _1, _2, substitutions["MESSAGE"].asString(),group)); // FS:LO FIRE-5230 - Chat Console Improvement: Replacing the "IM" in front of group chat messages with the actual group name } } else { // arrange a channel on a screen if(!mChannel.get()->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { LLSD substitutions = notification->getSubstitutions(); // According to comments in LLIMMgr::addMessage(), if we get message // from ourselves, the sender id is set to null. This fixes EXT-875. LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); if (avatar_id.isNull()) avatar_id = gAgentID; LLToastIMPanel::Params im_p; im_p.notification = notification; im_p.avatar_id = avatar_id; im_p.from = substitutions["FROM"].asString(); im_p.time = substitutions["TIME"].asString(); im_p.message = substitutions["MESSAGE"].asString(); im_p.session_id = substitutions["SESSION_ID"].asUUID(); LLToastIMPanel* im_box = new LLToastIMPanel(im_p); LLToast::Params p; p.notif_id = notification->getID(); p.session_id = im_p.session_id; p.notification = notification; p.panel = im_box; p.can_be_stored = false; p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); // send a signal to the counter manager; mNewNotificationSignal(); } else if (notify["sigtype"].asString() == "delete") { mChannel.get()->killToastByNotificationID(notification->getID()); } } return false; }
//-------------------------------------------------------------------------- bool LLScriptHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add") { // Don't log persisted notifications a second time if (!notification->isPersisted()) { // Archive message in nearby chat if desired if (LLHandlerUtil::canLogToNearbyChat(notification)) { LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); } // Archive message in instant message if desired if (LLHandlerUtil::canLogToIM(notification)) { LLHandlerUtil::logToIMP2P(notification); } } if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) { LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); } else { LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) { channel->addToast(p); } // send a signal to the counter manager mNewNotificationSignal(); } } else if (notify["sigtype"].asString() == "delete") { if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } else { mChannel->killToastByNotificationID(notification->getID()); } } return false; }
//-------------------------------------------------------------------------- bool LLTipHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { // archive message in nearby chat if (LLHandlerUtil::canLogToNearbyChat(notification)) { LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance< LLNearbyChat>("nearby_chat", LLSD()); if (nearby_chat->getVisible()) { return true; } } const std::string name = notification->getSubstitutions()["NAME"]; LLUUID from_id = notification->getPayload()["from_id"]; if (LLHandlerUtil::canLogToIM(notification)) { LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, name, name, notification->getMessage(), from_id, from_id); } if (LLHandlerUtil::canSpawnIMSession(notification)) { LLHandlerUtil::spawnIMSession(name, from_id); } // don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) if (!LLHandlerUtil::canSpawnToast(notification)) { return true; } LLToastPanel* notify_box = NULL; if("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) { LLOnlineStatusToast::Params p; p.notification = notification; p.message = notification->getMessage(); p.avatar_id = notification->getPayload()["FROM_ID"]; notify_box = new LLOnlineStatusToast(p); } else { notify_box = new LLToastNotifyPanel(notification); } LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); p.panel = notify_box; p.is_tip = true; p.can_be_stored = false; removeExclusiveNotifications(notification); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); } return true; }
//-------------------------------------------------------------------------- bool LLOfferHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { if( notification->getPayload().has("give_inventory_notification") && !notification->getPayload()["give_inventory_notification"] ) { // This is an original inventory offer, so add a script floater LLScriptFloaterManager::instance().onAddNotification(notification->getID()); } else { notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); LLUUID session_id; // if (LLHandlerUtil::canSpawnIMSession(notification)) // [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f // Don't spawn a new IM session for inventory offers if this notification was subject to @shownames=n // RELEASE-RLVa: [SL-2.3.0] Test on every new release to make sure the notification gets routed the way we want it to be bool fSpawnIM = (LLHandlerUtil::canSpawnIMSession(notification)) && (!notification->getPayload().has("rlv_shownames")); if (fSpawnIM) // [/RLVa:KB] { const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; session_id = LLHandlerUtil::spawnIMSession(name, from_id); } bool show_toast = LLHandlerUtil::canSpawnToast(notification); // bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); // [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f // NOTE: add_notid_to_im needs to be FALSE if we suppressed spawning an IM because in that case the notification needs to // be routed to the "syswell" or the inventory offer floater will dissapear and the user won't be able to accept it bool add_notid_to_im = (fSpawnIM) && (LLHandlerUtil::canAddNotifPanelToIM(notification)); // [/RLVa:KB] if (add_notid_to_im) { LLHandlerUtil::addNotifPanelToIM(notification); } if (notification->getPayload().has("SUPPRESS_TOAST") && notification->getPayload()["SUPPRESS_TOAST"]) { LLNotificationsUtil::cancel(notification); } else if(show_toast) { LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); // don't close notification on panel destroy since it will be used by IM floater notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notid_to_im; LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); // if we not add notification to IM - add it to notification well if (!add_notid_to_im) { // send a signal to the counter manager mNewNotificationSignal(); } } if (LLHandlerUtil::canLogToIM(notification)) { // log only to file if notif panel can be embedded to IM and IM is opened // [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f if (notification->getPayload().has("rlv_shownames")) { // Log to chat history if this notification was subject to @shownames=n LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); } else if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) // [/RLVa:KB] // if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) { LLHandlerUtil::logToIMP2P(notification, true); } else { LLHandlerUtil::logToIMP2P(notification); } } } } else if (notify["sigtype"].asString() == "delete") { if( notification->getPayload().has("give_inventory_notification") && !notification->getPayload()["give_inventory_notification"] ) { // Remove original inventory offer script floater LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); } else { // if (LLHandlerUtil::canAddNotifPanelToIM(notification) // && !LLHandlerUtil::isIMFloaterOpened(notification)) // [SL:KB] - Checked: 2010-04-20 (RLVa-1.2.2a) | Added: RLVa-1.2.0f // Repro: // 1) have someone drop you 2 inventory items (new IM session will be spawned) // 2) accept/decline the inventory offers as they come in // -> unread IM counter shows 0 // 3) toggle "Enable plain text chat history" while the IM session with the inventory offers isn't the active session // -> unread IM counter shows -2 // -> LLHandlerUtil::decIMMesageCounter() really should be fixed to check for "0" before decreasing the count but // there are enough bugfixes in RLVa as it is already :( // Fix: // - the one and only time we need to decrease the unread IM count is when we've clicked any of the buttons on the *toast* // - since LLIMFloater::updateMessages() hides the toast when we open the IM (which resets the unread count to 0) we should // *only* decrease the unread IM count if there's a visible toast since the unread count will be at 0 otherwise anyway LLScreenChannel* pChannel = dynamic_cast<LLScreenChannel*>(mChannel); LLToast* pToast = (pChannel) ? pChannel->getToastByNotificationID(notification->getID()) : NULL; if ( (pToast) && (!pToast->getCanBeStored()) ) // [/SL:KB] { LLHandlerUtil::decIMMesageCounter(notification); } mChannel->killToastByNotificationID(notification->getID()); } } return false; }
//-------------------------------------------------------------------------- bool LLOfferHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { if( notification->getPayload().has("give_inventory_notification") && !notification->getPayload()["give_inventory_notification"] ) { // This is an original inventory offer, so add a script floater LLScriptFloaterManager::instance().onAddNotification(notification->getID()); } else { notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); LLUUID session_id; if (LLHandlerUtil::canSpawnIMSession(notification)) { const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; session_id = LLHandlerUtil::spawnIMSession(name, from_id); } bool show_toast = LLHandlerUtil::canSpawnToast(notification); bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); if (add_notid_to_im) { LLHandlerUtil::addNotifPanelToIM(notification); } if (notification->getPayload().has("SUPPRESS_TOAST") && notification->getPayload()["SUPPRESS_TOAST"]) { LLNotificationsUtil::cancel(notification); } else if(show_toast) { LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); // don't close notification on panel destroy since it will be used by IM floater notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notid_to_im; LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); // if we not add notification to IM - add it to notification well if (!add_notid_to_im) { // send a signal to the counter manager mNewNotificationSignal(); } } if (LLHandlerUtil::canLogToNearbyChat(notification)) { LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); } if (LLHandlerUtil::canLogToIM(notification)) { // log only to file if notif panel can be embedded to IM and IM is opened if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) { LLHandlerUtil::logToIMP2P(notification, true); } else { LLHandlerUtil::logToIMP2P(notification); } } } } else if (notify["sigtype"].asString() == "delete") { if( notification->getPayload().has("give_inventory_notification") && !notification->getPayload()["give_inventory_notification"] ) { // Remove original inventory offer script floater LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); } else { if (LLHandlerUtil::canAddNotifPanelToIM(notification) && !LLHandlerUtil::isIMFloaterOpened(notification)) { LLHandlerUtil::decIMMesageCounter(notification); } mChannel->killToastByNotificationID(notification->getID()); } } return false; }
//-------------------------------------------------------------------------- bool LLTipHandler::processNotification(const LLSD& notify) { if(!mChannel) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { // archive message in nearby chat if (LLHandlerUtil::canLogToNearbyChat(notification)) { LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance< LLNearbyChat>("nearby_chat", LLSD()); if (nearby_chat->getVisible()) { return false; } } std::string session_name = notification->getPayload()["SESSION_NAME"]; const std::string name = notification->getSubstitutions()["NAME"]; if (session_name.empty()) { session_name = name; } LLUUID from_id = notification->getPayload()["from_id"]; if (LLHandlerUtil::canLogToIM(notification)) { // LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, // notification->getMessage(), from_id, from_id); // [SL:KB] - Patch: Chat-Logs | Checked: 2010-11-18 (Catznip-2.4.0c) | Added: Catznip-2.4.0c LLHandlerUtil::logToIMP2P(notification, false); // [/SL:KB] } if (LLHandlerUtil::canSpawnIMSession(notification)) { LLHandlerUtil::spawnIMSession(name, from_id); } // don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) if (!LLHandlerUtil::canSpawnToast(notification)) { return false; } LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); p.panel = notify_box; p.is_tip = true; p.can_be_stored = false; removeExclusiveNotifications(notification); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); if(channel) channel->addToast(p); } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); } return false; }
//--------------------------------------------------------------------------- // Singu Note: We could clean a lot of this up by creating derived classes for Notifications and NotificationTips. LLNotifyBox::LLNotifyBox(LLNotificationPtr notification) : LLPanel(notification->getName(), LLRect(), BORDER_NO), LLEventTimer(notification->getExpiration() == LLDate() ? LLDate(LLDate::now().secondsSinceEpoch() + (F64)gSavedSettings.getF32("NotifyTipDuration")) : notification->getExpiration()), LLInstanceTracker<LLNotifyBox, LLUUID>(notification->getID()), mNotification(notification), mIsTip(notification->getType() == "notifytip"), mAnimating(gNotifyBoxView->getChildCount() == 0), // Only animate first window mNextBtn(NULL), mNumOptions(0), mNumButtons(0), mAddedDefaultBtn(false), mUserInputBox(NULL) { std::string edit_text_name; std::string edit_text_contents; // setup paramaters const std::string& message(notification->getMessage()); // initialize setFocusRoot(!mIsTip); // caution flag can be set explicitly by specifying it in the // notification payload, or it can be set implicitly if the // notify xml template specifies that it is a caution // // tip-style notification handle 'caution' differently - // they display the tip in a different color mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; LLNotificationFormPtr form(notification->getForm()); mNumOptions = form->getNumElements(); bool is_textbox = form->getElement("message").isDefined(); bool layout_script_dialog(notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); LLRect rect = mIsTip ? getNotifyTipRect(message) : getNotifyRect(is_textbox ? 10 : mNumOptions, layout_script_dialog, mIsCaution); if ((form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE || form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)) rect.mBottom -= BTN_HEIGHT; setRect(rect); setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT)); setBackgroundVisible(FALSE); setBackgroundOpaque(TRUE); const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32); const S32 BOTTOM = (S32)sFont->getLineHeight(); S32 x = HPAD + HPAD; S32 y = TOP; auto icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), mIsTip ? "notify_tip_icon.tga" : mIsCaution ? "notify_caution_icon.tga" : "notify_box_icon.tga"); icon->setMouseOpaque(FALSE); addChild(icon); x += HPAD + HPAD + 32; // add a caution textbox at the top of a caution notification if (mIsCaution && !mIsTip) { S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD; auto caution_box = new LLTextBox( std::string("caution_box"), LLRect(x, y, getRect().getWidth() - 2, caution_height), LLStringUtil::null, sFont, FALSE); caution_box->setFontStyle(LLFontGL::BOLD); caution_box->setColor(gColors.getColor("NotifyCautionWarnColor")); caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); caution_box->setBorderVisible(FALSE); caution_box->setWrappedText(notification->getMessage()); addChild(caution_box); // adjust the vertical position of the next control so that // it appears below the caution textbox y = y - caution_height; } else { const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); // Tokenization on \n is handled by LLTextBox const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. auto text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, LLStringUtil::null, sFont, FALSE, true); text->setWordWrap(TRUE); text->setMouseOpaque(TRUE); text->setBorderVisible(FALSE); text->setTakesNonScrollClicks(TRUE); text->setHideScrollbarForShortDocs(TRUE); text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually // rendered under the text box, therefore we want // the actual text box to be transparent auto text_color = gColors.getColor(mIsCaution && mIsTip ? "NotifyCautionWarnColor" : "NotifyTextColor"); text->setReadOnlyFgColor(text_color); //sets caution text color for tip notifications if (!mIsCaution) // We could do some extra color math here to determine if bg's too close to link color, but let's just cross with the link color instead text->setLinkColor(new LLColor4(lerp(text_color, gSavedSettings.getColor4("HTMLLinkColor"), 0.4f))); text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) text->appendText(message,false,false,nullptr,!layout_script_dialog); // Now we can set the text, since colors have been set. addChild(text); } if (mIsTip) { chat_notification(mNotification); } else { mNextBtn = new LLButton(std::string("next"), LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD), std::string("notify_next.png"), std::string("notify_next.png"), LLStringUtil::null, boost::bind(&LLNotifyBox::moveToBack, this, true), sFont); mNextBtn->setScaleImage(TRUE); mNextBtn->setToolTip(LLTrans::getString("next")); addChild(mNextBtn); for (S32 i = 0; i < mNumOptions; i++) { LLSD form_element = form->getElement(i); std::string element_type = form_element["type"].asString(); if (element_type == "button") { addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean(), layout_script_dialog); } else if (element_type == "input") { edit_text_contents = form_element["value"].asString(); edit_text_name = form_element["name"].asString(); } } if (is_textbox) { S32 button_rows = layout_script_dialog ? 2 : 1; LLRect input_rect; input_rect.setOriginAndSize(x, BOTTOM_PAD + button_rows * (BTN_HEIGHT + VPAD), 3 * 80 + 4 * HPAD, button_rows * (BTN_HEIGHT + VPAD) + BTN_HEIGHT); mUserInputBox = new LLTextEditor(edit_text_name, input_rect, 254, edit_text_contents, sFont, FALSE); mUserInputBox->setBorderVisible(TRUE); mUserInputBox->setTakesNonScrollClicks(TRUE); mUserInputBox->setHideScrollbarForShortDocs(TRUE); mUserInputBox->setWordWrap(TRUE); mUserInputBox->setTabsToNextField(FALSE); mUserInputBox->setCommitOnFocusLost(FALSE); mUserInputBox->setAcceptCallingCardNames(FALSE); mUserInputBox->setHandleEditKeysDirectly(TRUE); addChild(mUserInputBox, -1); } else { setIsChrome(TRUE); } if (mNumButtons == 0) { addButton("OK", "OK", false, true, layout_script_dialog); mAddedDefaultBtn = true; } std::string check_title; if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE) { check_title = LLNotificationTemplates::instance().getGlobalString("skipnexttime"); } else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) { check_title = LLNotificationTemplates::instance().getGlobalString("alwayschoose"); } if (!check_title.empty()) { const LLFontGL* font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF); S32 line_height = llfloor(font->getLineHeight() + 0.99f); // Extend dialog for "check next time" S32 max_msg_width = getRect().getWidth() - HPAD * 9; S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16; max_msg_width = llmax(max_msg_width, check_width); S32 msg_x = (getRect().getWidth() - max_msg_width) / 2; LLRect check_rect; check_rect.setOriginAndSize(msg_x, BOTTOM_PAD + BTN_HEIGHT + VPAD*2 + (BTN_HEIGHT + VPAD) * (mNumButtons / 3), max_msg_width, line_height); LLCheckboxCtrl* check = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font, // Lambda abuse. [this](LLUICtrl* ctrl, const LLSD& param) { this->mNotification->setIgnored(ctrl->getValue()); }); check->setEnabledColor(LLUI::sColorsGroup->getColor(mIsCaution ? "AlertCautionTextColor" : "AlertTextColor")); if (mIsCaution) { check->setButtonColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); } addChild(check); } if (++sNotifyBoxCount <= 0) LL_WARNS() << "A notification was mishandled. sNotifyBoxCount = " << sNotifyBoxCount << LL_ENDL; // If this is the only notify box, don't show the next button else if (sNotifyBoxCount == 1 && mNextBtn) mNextBtn->setVisible(false); } }
//--------------------------------------------------------------------------- LLNotifyBox::LLNotifyBox(LLNotificationPtr notification, BOOL layout_script_dialog) : LLPanel(notification->getName(), LLRect(), BORDER_NO), LLEventTimer(notification->getExpiration() == LLDate() ? LLDate(LLDate::now().secondsSinceEpoch() + (F64)gSavedSettings.getF32("NotifyTipDuration")) : notification->getExpiration()), LLInstanceTracker<LLNotifyBox, LLUUID>(notification->getID()), mNotification(notification), mIsTip(notification->getType() == "notifytip"), mAnimating(TRUE), mNextBtn(NULL), mNumOptions(0), mNumButtons(0), mAddedDefaultBtn(FALSE), mLayoutScriptDialog(layout_script_dialog) { // clicking on a button does not steal current focus setIsChrome(TRUE); // class init if (!sFont) { sFont = LLFontGL::getFontSansSerif(); sFontSmall = LLFontGL::getFontSansSerifSmall(); } // setup paramaters mMessage = notification->getMessage(); // initialize setFocusRoot(!mIsTip); // caution flag can be set explicitly by specifying it in the // notification payload, or it can be set implicitly if the // notify xml template specifies that it is a caution // // tip-style notification handle 'caution' differently - // they display the tip in a different color mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; // Only animate first window if( gNotifyBoxView->getChildCount() > 0 ) mAnimating = FALSE; else mAnimating = TRUE; LLNotificationFormPtr form(notification->getForm()); mNumOptions = form->getNumElements(); LLRect rect = mIsTip ? getNotifyTipRect(mMessage) : getNotifyRect(mNumOptions, layout_script_dialog, mIsCaution); setRect(rect); setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT)); setBackgroundVisible(FALSE); setBackgroundOpaque(TRUE); LLIconCtrl* icon; LLTextEditor* text; const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32); const S32 BOTTOM = (S32)sFont->getLineHeight(); S32 x = HPAD + HPAD; S32 y = TOP; if (mIsTip) { // use the tip notification icon icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_tip_icon.tga")); } else if (mIsCaution) { // use the caution notification icon icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_caution_icon.tga")); } else { // use the default notification icon icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_box_icon.tga")); } icon->setMouseOpaque(FALSE); addChild(icon); x += HPAD + HPAD + 32; // add a caution textbox at the top of a caution notification LLTextBox* caution_box = NULL; if (mIsCaution && !mIsTip) { S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD; caution_box = new LLTextBox( std::string("caution_box"), LLRect(x, y, getRect().getWidth() - 2, caution_height), LLStringUtil::null, sFont, FALSE); caution_box->setFontStyle(LLFontGL::BOLD); caution_box->setColor(gColors.getColor("NotifyCautionWarnColor")); caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); caution_box->setBorderVisible(FALSE); caution_box->setWrappedText(notification->getMessage()); addChild(caution_box); // adjust the vertical position of the next control so that // it appears below the caution textbox y = y - caution_height; } else { const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); // Tokenization on \n is handled by LLTextBox const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, mMessage, sFont, FALSE); text->setWordWrap(TRUE); text->setTabStop(FALSE); text->setMouseOpaque(FALSE); text->setBorderVisible(FALSE); text->setTakesNonScrollClicks(FALSE); text->setHideScrollbarForShortDocs(TRUE); text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually // rendered under the text box, therefore we want // the actual text box to be transparent text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") ); text->setEnabled(FALSE); // makes it read-only text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) addChild(text); } if (mIsTip) { // TODO: Make a separate archive for these. LLChat chat(mMessage); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::getInstance(LLSD())->addChatHistory(chat); } else { LLButton* btn; btn = new LLButton(std::string("next"), LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD), std::string("notify_next.png"), std::string("notify_next.png"), LLStringUtil::null, onClickNext, this, sFont); btn->setScaleImage(TRUE); btn->setToolTip(std::string("Next")); // *TODO: Translate addChild(btn); mNextBtn = btn; for (S32 i = 0; i < mNumOptions; i++) { LLSD form_element = form->getElement(i); if (form_element["type"].asString() != "button") { continue; } addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean()); } if (mNumButtons == 0) { addButton("OK", "OK", FALSE, TRUE); mAddedDefaultBtn = TRUE; } sNotifyBoxCount++; if (sNotifyBoxCount <= 0) { llwarns << "A notification was mishandled. sNotifyBoxCount = " << sNotifyBoxCount << llendl; } // If this is the only notify box, don't show the next button if (sNotifyBoxCount == 1 && mNextBtn) { mNextBtn->setVisible(FALSE); } } }
//--------------------------------------------------------------------------- // Singu Note: We could clean a lot of this up by creating derived classes for Notifications and NotificationTips. LLNotifyBox::LLNotifyBox(LLNotificationPtr notification) : LLPanel(notification->getName(), LLRect(), BORDER_NO), LLEventTimer(notification->getExpiration() == LLDate() ? LLDate(LLDate::now().secondsSinceEpoch() + (F64)gSavedSettings.getF32("NotifyTipDuration")) : notification->getExpiration()), LLInstanceTracker<LLNotifyBox, LLUUID>(notification->getID()), mNotification(notification), mIsTip(notification->getType() == "notifytip"), mAnimating(gNotifyBoxView->getChildCount() == 0), // Only animate first window mNextBtn(NULL), mNumOptions(0), mNumButtons(0), mAddedDefaultBtn(false), mUserInputBox(NULL) { std::string edit_text_name; std::string edit_text_contents; // setup paramaters const std::string& message(notification->getMessage()); // initialize setFocusRoot(!mIsTip); // caution flag can be set explicitly by specifying it in the // notification payload, or it can be set implicitly if the // notify xml template specifies that it is a caution // // tip-style notification handle 'caution' differently - // they display the tip in a different color mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; LLNotificationFormPtr form(notification->getForm()); mNumOptions = form->getNumElements(); bool is_textbox = form->getElement("message").isDefined(); bool layout_script_dialog(notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); LLRect rect = mIsTip ? getNotifyTipRect(message) : getNotifyRect(is_textbox ? 10 : mNumOptions, layout_script_dialog, mIsCaution); setRect(rect); setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT)); setBackgroundVisible(FALSE); setBackgroundOpaque(TRUE); LLIconCtrl* icon; LLTextEditor* text; const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32); const S32 BOTTOM = (S32)sFont->getLineHeight(); S32 x = HPAD + HPAD; S32 y = TOP; if (mIsTip) { // use the tip notification icon icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_tip_icon.tga")); } else if (mIsCaution) { // use the caution notification icon icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_caution_icon.tga")); } else { // use the default notification icon icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), std::string("notify_box_icon.tga")); } icon->setMouseOpaque(FALSE); addChild(icon); x += HPAD + HPAD + 32; // add a caution textbox at the top of a caution notification LLTextBox* caution_box = NULL; if (mIsCaution && !mIsTip) { S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD; caution_box = new LLTextBox( std::string("caution_box"), LLRect(x, y, getRect().getWidth() - 2, caution_height), LLStringUtil::null, sFont, FALSE); caution_box->setFontStyle(LLFontGL::BOLD); caution_box->setColor(gColors.getColor("NotifyCautionWarnColor")); caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); caution_box->setBorderVisible(FALSE); caution_box->setWrappedText(notification->getMessage()); addChild(caution_box); // adjust the vertical position of the next control so that // it appears below the caution textbox y = y - caution_height; } else if (mIsCaution && mIsTip) { const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); // Tokenization on \n is handled by LLTextBox const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, message, sFont, FALSE); text->setWordWrap(TRUE); text->setTabStop(FALSE); text->setMouseOpaque(FALSE); text->setBorderVisible(FALSE); text->setTakesNonScrollClicks(FALSE); text->setHideScrollbarForShortDocs(TRUE); text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually // rendered under the text box, therefore we want // the actual text box to be transparent text->setReadOnlyFgColor ( gColors.getColor("NotifyCautionWarnColor") ); //sets caution text color for tip notifications text->setEnabled(FALSE); // makes it read-only text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) addChild(text); } else { const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); // Tokenization on \n is handled by LLTextBox const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, message, sFont, FALSE); text->setWordWrap(TRUE); text->setTabStop(FALSE); text->setMouseOpaque(FALSE); text->setBorderVisible(FALSE); text->setTakesNonScrollClicks(FALSE); text->setHideScrollbarForShortDocs(TRUE); text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually // rendered under the text box, therefore we want // the actual text box to be transparent text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") ); text->setEnabled(FALSE); // makes it read-only text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) addChild(text); } if (mIsTip) { chat_notification(mNotification); } else { mNextBtn = new LLButton(std::string("next"), LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD), std::string("notify_next.png"), std::string("notify_next.png"), LLStringUtil::null, boost::bind(&LLNotifyBox::moveToBack, this, true), sFont); mNextBtn->setScaleImage(TRUE); mNextBtn->setToolTip(LLTrans::getString("next")); addChild(mNextBtn); for (S32 i = 0; i < mNumOptions; i++) { LLSD form_element = form->getElement(i); std::string element_type = form_element["type"].asString(); if (element_type == "button") { addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean(), layout_script_dialog); } else if (element_type == "input") { edit_text_contents = form_element["value"].asString(); edit_text_name = form_element["name"].asString(); } } if (is_textbox) { S32 button_rows = layout_script_dialog ? 2 : 1; LLRect input_rect; input_rect.setOriginAndSize(x, BOTTOM_PAD + button_rows * (BTN_HEIGHT + VPAD), 3 * 80 + 4 * HPAD, button_rows * (BTN_HEIGHT + VPAD) + BTN_HEIGHT); mUserInputBox = new LLTextEditor(edit_text_name, input_rect, 254, edit_text_contents, sFont, FALSE); mUserInputBox->setBorderVisible(TRUE); mUserInputBox->setTakesNonScrollClicks(TRUE); mUserInputBox->setHideScrollbarForShortDocs(TRUE); mUserInputBox->setWordWrap(TRUE); mUserInputBox->setTabsToNextField(FALSE); mUserInputBox->setCommitOnFocusLost(FALSE); mUserInputBox->setAcceptCallingCardNames(FALSE); mUserInputBox->setHandleEditKeysDirectly(TRUE); addChild(mUserInputBox, -1); } else { setIsChrome(TRUE); } if (mNumButtons == 0) { addButton("OK", "OK", false, true, layout_script_dialog); mAddedDefaultBtn = true; } if (++sNotifyBoxCount <= 0) LL_WARNS() << "A notification was mishandled. sNotifyBoxCount = " << sNotifyBoxCount << LL_ENDL; // If this is the only notify box, don't show the next button else if (sNotifyBoxCount == 1 && mNextBtn) mNextBtn->setVisible(false); } }
//-------------------------------------------------------------------------- bool LLScriptHandler::processNotification(const LLSD& notify) { if(mChannel.isDead()) { return false; } LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) return false; // arrange a channel on a screen if(!mChannel.get()->getVisible()) { initChannel(); } if(notify["sigtype"].asString() == "add") { if (LLHandlerUtil::canLogToIM(notification)) { LLHandlerUtil::logToIMP2P(notification); } if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) { LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); } else { LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) { channel->addToast(p); } // send a signal to the counter manager mNewNotificationSignal(); } } else if (notify["sigtype"].asString() == "delete") { if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } else { mChannel.get()->killToastByNotificationID(notification->getID()); } } return false; }