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); } }
LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal) : LLToastPanel(notification), mDefaultOption( 0 ), mCheck(NULL), mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH), mLabel(notification->getName()), mLineEditor(NULL) { const LLFontGL* font = LLFontGL::getFontSansSerif(); const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); const S32 EDITOR_HEIGHT = 20; LLNotificationFormPtr form = mNotification->getForm(); std::string edit_text_name; std::string edit_text_contents; S32 edit_text_max_chars = 0; bool is_password = false; LLToastPanel::setBackgroundVisible(FALSE); LLToastPanel::setBackgroundOpaque(TRUE); typedef std::vector<std::pair<std::string, std::string> > options_t; options_t supplied_options; // for now, get LLSD to iterator over form elements LLSD form_sd = form->asLLSD(); S32 option_index = 0; for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it) { std::string type = (*it)["type"].asString(); if (type == "button") { if((*it)["default"]) { mDefaultOption = option_index; } supplied_options.push_back(std::make_pair((*it)["name"].asString(), (*it)["text"].asString())); ButtonData data; if (option_index == mNotification->getURLOption()) { data.mURL = mNotification->getURL(); data.mURLExternal = mNotification->getURLOpenExternally(); } mButtonData.push_back(data); option_index++; } else if (type == "text") { edit_text_contents = (*it)["value"].asString(); edit_text_name = (*it)["name"].asString(); edit_text_max_chars = (*it)["max_length_chars"].asInteger(); } else if (type == "password") { edit_text_contents = (*it)["value"].asString(); edit_text_name = (*it)["name"].asString(); is_password = true; } } // Buttons options_t options; if (supplied_options.empty()) { options.push_back(std::make_pair(std::string("close"), LLNotifications::instance().getGlobalString("implicitclosebutton"))); // add data for ok button. ButtonData ok_button; mButtonData.push_back(ok_button); mDefaultOption = 0; } else { options = supplied_options; } S32 num_options = options.size(); // Calc total width of buttons S32 button_width = 0; S32 sp = font->getWidth(std::string("OO")); for( S32 i = 0; i < num_options; i++ ) { S32 w = S32(font->getWidth( options[i].second ) + 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 = mNotification->getMessage(); llwarns << "Alert: " << msg << llendl; LLTextBox::Params params; params.name("Alert message"); params.font(font); params.tab_stop(false); params.wrap(true); params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); params.allow_scroll(true); LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params); // Compute max allowable height for the dialog text, so we can allocate // space before wrapping the text to fit. S32 max_allowed_msg_height = gFloaterView->getRect().getHeight() - LINE_HEIGHT // title bar - 3*VPAD - BTN_HEIGHT; // reshape to calculate real text width and height msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height ); msg_box->setValue(msg); S32 pixel_width = msg_box->getTextPixelWidth(); S32 pixel_height = msg_box->getTextPixelHeight(); // We should use some space to prevent set textbox's scroller visible when it is unnecessary. msg_box->reshape( llmin(MAX_ALLOWED_MSG_WIDTH,pixel_width + 2 * msg_box->getHPad() + HPAD), llmin(max_allowed_msg_height,pixel_height + 2 * msg_box->getVPad()) ) ; 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; } LLToastPanel::reshape( dialog_width, dialog_height, FALSE ); S32 msg_y = LLToastPanel::getRect().getHeight() - VPAD; S32 msg_x = HPAD; if (hasTitleBar()) { msg_y -= LINE_HEIGHT; // room for title } static LLUIColor alert_caution_text_color = LLUIColorTable::instance().getColor("AlertCautionTextColor"); if (mCaution) { LLIconCtrl* icon = LLUICtrlFactory::getInstance()->createFromFile<LLIconCtrl>("alert_icon.xml", this, LLPanel::child_registry_t::instance()); if(icon) { icon->setRect(LLRect(msg_x, msg_y, msg_x+32, msg_y-32)); LLToastPanel::addChild(icon); } msg_x += 32 + HPAD; msg_box->setColor( alert_caution_text_color ); } LLRect rect; rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() ); msg_box->setRect( rect ); LLToastPanel::addChild(msg_box); // (Optional) Edit Box if (!edit_text_name.empty()) { S32 y = VPAD + BTN_HEIGHT + VPAD/2; mLineEditor = LLUICtrlFactory::getInstance()->createFromFile<LLLineEditor>("alert_line_editor.xml", this, LLPanel::child_registry_t::instance()); if (mLineEditor) { LLRect leditor_rect = LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y); mLineEditor->setName(edit_text_name); mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight()); mLineEditor->setRect(leditor_rect); mLineEditor->setMaxTextChars(edit_text_max_chars); mLineEditor->setText(edit_text_contents); // decrease limit of line editor of teleport offer dialog to avoid truncation of // location URL in invitation message, see EXT-6891 if ("OfferTeleport" == mNotification->getName()) { mLineEditor->setMaxTextLength(gSavedSettings.getS32( "teleport_offer_invitation_max_length")); } else { mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1); } LLToastPanel::addChild(mLineEditor); mLineEditor->setDrawAsterixes(is_password); setEditTextArgs(notification->getSubstitutions()); mLineEditor->setFollowsLeft(); mLineEditor->setFollowsRight(); // find form text input field LLSD form_text; for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it) { std::string type = (*it)["type"].asString(); if (type == "text") { form_text = (*it); } } // if form text input field has width attribute if (form_text.has("width")) { // adjust floater width to fit line editor S32 editor_width = form_text["width"]; LLRect editor_rect = mLineEditor->getRect(); U32 width_delta = editor_width - editor_rect.getWidth(); LLRect toast_rect = getRect(); reshape(toast_rect.getWidth() + width_delta, toast_rect.getHeight()); } } } // Buttons S32 button_left = (LLToastPanel::getRect().getWidth() - btn_total_width) / 2; for( S32 i = 0; i < num_options; i++ ) { LLRect button_rect; LLButton* btn = LLUICtrlFactory::getInstance()->createFromFile<LLButton>("alert_button.xml", this, LLPanel::child_registry_t::instance()); if(btn) { btn->setName(options[i].first); btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT )); btn->setLabel(options[i].second); btn->setFont(font); btn->setClickedCallback(boost::bind(&LLToastAlertPanel::onButtonPressed, this, _2, i)); mButtonData[i].mButton = btn; LLToastPanel::addChild(btn); if( i == mDefaultOption ) { btn->setFocus(TRUE); } } button_left += button_width + BTN_HPAD; } std::string ignore_label; if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE) { setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label); } else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) { setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label); } // *TODO: check necessity of this code //gFloaterView->adjustToFitScreen(this, FALSE); if (mLineEditor) { mLineEditor->selectAll(); } if(mDefaultOption >= 0) { // delay before enabling default button mDefaultBtnTimer.start(); mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY); } LLTransientFloaterMgr::instance().addControlView( LLTransientFloaterMgr::GLOBAL, this); }
void LLAlertDialog::createDialog(const std::vector<LLString>* optionsp, S32 default_option, const LLString& msg_in, const LLString::format_map_t& args, const LLString& edit_text) { setBackgroundVisible(TRUE); setBackgroundOpaque(TRUE); const LLFontGL* font = gResMgr->getRes( font_name ); const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); const S32 EDITOR_HEIGHT = 20; // Buttons std::vector<LLString> default_option_list; mNumOptions = optionsp->size(); if( 0 == mNumOptions ) { default_option_list.push_back("Close"); optionsp = &default_option_list; default_option = 0; mNumOptions = 1; } const std::vector<LLString>& options = *optionsp; mButtonData = new ButtonData[mNumOptions]; // Calc total width of buttons S32 button_width = 0; S32 sp = font->getWidth("OO"); for( S32 i = 0; i < mNumOptions; i++ ) { S32 w = S32(font->getWidth( options[i] ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD; button_width = llmax( w, button_width ); } S32 btn_total_width = button_width; if( mNumOptions > 1 ) { btn_total_width = (mNumOptions * button_width) + ((mNumOptions - 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 LLString msg = msg_in; format( msg, args ); llwarns << "Alert: " << msg << llendl; LLTextBox* msg_box = new LLTextBox( "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 } if (edit_text.size() > 0) { dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f)); dialog_height += EDITOR_HEIGHT; } if (mCaution) { // Make room for the caution icon. dialog_width += 32 + HPAD; } reshape( dialog_width, dialog_height, FALSE ); S32 msg_y = mRect.getHeight() - VPAD; S32 msg_x = HPAD; if (hasTitleBar()) { msg_y -= LINE_HEIGHT; // room for title } if (mCaution) { LLIconCtrl* icon = new LLIconCtrl("icon", LLRect(msg_x, msg_y, msg_x+32, msg_y-32), "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 = (mRect.getWidth() - btn_total_width) / 2; for( S32 i = 0; i < mNumOptions; i++ ) { LLRect button_rect; button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ); LLButton* btn = new LLButton( "btn", button_rect, "","", "", &LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i]), font, options[i], options[i]); mButtonData[i].mSelf = this; mButtonData[i].mButton = btn; mButtonData[i].mOption = i; addChild(btn); if( i == default_option ) { btn->setFocus(TRUE); } button_left += button_width + BTN_HPAD; } // (Optional) Edit Box if (edit_text.size() > 0) { S32 y = VPAD + BTN_HEIGHT + VPAD/2; mLineEditor = new LLLineEditor("lineeditor", LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y), edit_text, LLFontGL::sSansSerif, STD_STRING_STR_LEN); // make sure all edit keys get handled properly mLineEditor->setHandleEditKeysDirectly(TRUE); addChild(mLineEditor); } }