00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llnotify.h"
00035
00036 #include "llchat.h"
00037 #include "llfocusmgr.h"
00038 #include "llglimmediate.h"
00039
00040 #include "llbutton.h"
00041 #include "llfocusmgr.h"
00042 #include "llglheaders.h"
00043 #include "lliconctrl.h"
00044 #include "lltextbox.h"
00045 #include "lltexteditor.h"
00046 #include "lluiconstants.h"
00047 #include "llui.h"
00048 #include "llxmlnode.h"
00049 #include "llalertdialog.h"
00050 #include "llviewercontrol.h"
00051 #include "llviewerdisplay.h"
00052 #include "llviewerimagelist.h"
00053 #include "llfloaterchat.h"
00054 #include "lloverlaybar.h"
00055 #include "lluictrlfactory.h"
00056
00057
00058 LLNotifyBoxView* gNotifyBoxView = NULL;
00059
00060 const F32 ANIMATION_TIME = 0.333f;
00061
00062
00063 S32 LLNotifyBox::sNotifyBoxCount = 0;
00064 const LLFontGL* LLNotifyBox::sFont = NULL;
00065 const LLFontGL* LLNotifyBox::sFontSmall = NULL;
00066 std::map<LLString, LLNotifyBox*> LLNotifyBox::sOpenUniqueNotifyBoxes;
00067 LLPointer<LLNotifyBoxTemplate> LLNotifyBox::sDefaultTemplate;
00068
00069
00070 LLNotifyBox::template_map_t LLNotifyBox::sNotifyTemplates;
00071
00072 LLNotifyBox::LLNotifyBehavior::LLNotifyBehavior(notify_callback_t callback, void* data) :
00073 mCallback(callback),
00074 mData(data)
00075 {
00076 }
00077
00078
00079
00080
00081
00082
00083 LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, notify_callback_t callback, void *user_data)
00084 {
00085 return showXml(xml_desc, LLString::format_map_t(), callback, user_data);
00086 }
00087
00088
00089
00090 LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution,
00091 notify_callback_t callback, void *user_data)
00092 {
00093
00094 LLPointer<LLNotifyBoxTemplate> xml_template = getTemplate(xml_desc);
00095 LLNotifyBox* notify = findExistingNotify(xml_template, args);
00096 if (notify)
00097 {
00098 delete notify->mBehavior;
00099 notify->mBehavior = new LLNotifyBehavior(callback, user_data);
00100 }
00101 else
00102 {
00103 notify = new LLNotifyBox(xml_template, args, callback, user_data, is_caution);
00104 gNotifyBoxView->addChildAtEnd(notify);
00105 notify->moveToBack();
00106 }
00107 return notify;
00108 }
00109
00110
00111 LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
00112 notify_callback_t callback, void *user_data)
00113 {
00114 LLPointer<LLNotifyBoxTemplate> xml_template = getTemplate(xml_desc);
00115 LLNotifyBox* notify = findExistingNotify(xml_template, args);
00116 if (notify)
00117 {
00118 delete notify->mBehavior;
00119 notify->mBehavior = new LLNotifyBehavior(callback, user_data);
00120 }
00121 else
00122 {
00123 notify = new LLNotifyBox(xml_template, args, callback, user_data);
00124 gNotifyBoxView->addChildAtEnd(notify);
00125 notify->moveToBack();
00126 }
00127 return notify;
00128 }
00129
00130
00131 LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
00132 notify_callback_t callback, void *user_data,
00133 const option_list_t& options,
00134 BOOL layout_script_dialog)
00135 {
00136 LLPointer<LLNotifyBoxTemplate> xml_template = getTemplate(xml_desc);
00137 LLNotifyBox* notify = findExistingNotify(xml_template, args);
00138 if (notify)
00139 {
00140 delete notify->mBehavior;
00141 notify->mBehavior = new LLNotifyBehavior(callback, user_data);
00142 }
00143 else
00144 {
00145 notify = new LLNotifyBox(xml_template, args, callback, user_data, FALSE, options, layout_script_dialog);
00146 gNotifyBoxView->addChild(notify);
00147 }
00148 return notify;
00149 }
00150
00151
00152 LLNotifyBox* LLNotifyBox::findExistingNotify(LLPointer<LLNotifyBoxTemplate> notify_template, const LLString::format_map_t &args)
00153 {
00154 if(notify_template->mUnique)
00155 {
00156 LLString message = notify_template->mMessage;
00157 format(message, args);
00158 unique_map_t::iterator found_it = sOpenUniqueNotifyBoxes.find(notify_template->mLabel + message);
00159 if (found_it != sOpenUniqueNotifyBoxes.end())
00160 {
00161 return found_it->second;
00162 }
00163 }
00164 return NULL;
00165 }
00166
00167
00168 void LLNotifyBox::cleanup()
00169 {
00170 sDefaultTemplate = NULL;
00171 }
00172
00173
00174
00175 LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLString::format_map_t& args,
00176 notify_callback_t callback, void* user_data, BOOL is_caution,
00177 const option_list_t& extra_options,
00178 BOOL layout_script_dialog)
00179 : LLPanel(xml_template->mLabel, LLRect(), BORDER_NO),
00180 LLEventTimer(xml_template->mDuration),
00181 mIsTip(FALSE),
00182 mAnimating(TRUE),
00183 mUnique(xml_template->mUnique),
00184 mNextBtn(NULL),
00185 mBehavior(new LLNotifyBehavior(callback, user_data)),
00186 mNumOptions(0),
00187 mDefaultOption(0)
00188 {
00189
00190 setIsChrome(TRUE);
00191
00192
00193 if (!sFont)
00194 {
00195 sFont = LLFontGL::sSansSerif;
00196 sFontSmall = LLFontGL::sSansSerifSmall;
00197 }
00198
00199
00200
00201 mMessage = xml_template->mMessage;
00202 format(mMessage, args);
00203
00204
00205 if (mUnique)
00206 {
00207 sOpenUniqueNotifyBoxes[xml_template->mLabel + mMessage] = this;
00208 }
00209
00210 option_list_t options = xml_template->mOptions;
00211 options.insert(options.end(), extra_options.begin(), extra_options.end());
00212
00213
00214
00215 mIsTip = xml_template->mIsTip;
00216 setFocusRoot(!mIsTip);
00217
00218
00219
00220
00221
00222
00223
00224 mIsCaution = (xml_template->mIsCaution || is_caution);
00225
00226
00227 if( gNotifyBoxView->getChildCount() > 0 )
00228 mAnimating = FALSE;
00229 else
00230 mAnimating = TRUE;
00231
00232 mNumOptions = options.size();
00233 mDefaultOption = xml_template->mDefaultOption;
00234
00235 LLRect rect = mIsTip ? getNotifyTipRect(mMessage)
00236 : getNotifyRect(mNumOptions, layout_script_dialog, mIsCaution);
00237 setRect(rect);
00238 setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
00239 setBackgroundVisible(FALSE);
00240 setBackgroundOpaque(TRUE);
00241
00242 LLIconCtrl* icon;
00243 LLTextEditor* text;
00244
00245 const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
00246 const S32 BOTTOM = (S32)sFont->getLineHeight();
00247 S32 x = HPAD + HPAD;
00248 S32 y = TOP;
00249
00250 if (mIsTip)
00251 {
00252
00253 icon = new LLIconCtrl("icon", LLRect(x, y, x+32, TOP-32), "notify_tip_icon.tga");
00254 }
00255 else if (mIsCaution)
00256 {
00257
00258 icon = new LLIconCtrl("icon", LLRect(x, y, x+32, TOP-32), "notify_caution_icon.tga");
00259 }
00260 else
00261 {
00262
00263 icon = new LLIconCtrl("icon", LLRect(x, y, x+32, TOP-32), "notify_box_icon.tga");
00264 }
00265
00266 icon->setMouseOpaque(FALSE);
00267 addChild(icon);
00268
00269 x += HPAD + HPAD + 32;
00270
00271
00272 LLTextBox* caution_box = NULL;
00273 if (mIsCaution && !mIsTip)
00274 {
00275 S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD;
00276 caution_box = new LLTextBox(
00277 "caution_box",
00278 LLRect(x, y, getRect().getWidth() - 2, caution_height),
00279 "",
00280 sFont,
00281 FALSE);
00282
00283 caution_box->setFontStyle(LLFontGL::BOLD);
00284 caution_box->setColor(gColors.getColor("NotifyCautionWarnColor"));
00285 caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor"));
00286 caution_box->setBorderVisible(FALSE);
00287 caution_box->setWrappedText(LLNotifyBox::getTemplateMessage("ScriptQuestionCautionWarn"));
00288
00289 addChild(caution_box);
00290
00291
00292
00293 y = y - caution_height;
00294 }
00295
00296 const S32 BOTTOM_PAD = VPAD * 3;
00297 const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);
00298
00299
00300
00301 const S32 MAX_LENGTH = 512 + 20 +
00302 DB_FIRST_NAME_BUF_SIZE +
00303 DB_LAST_NAME_BUF_SIZE +
00304 DB_INV_ITEM_NAME_BUF_SIZE;
00305
00306 text = new LLTextEditor("box",
00307 LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16),
00308 MAX_LENGTH,
00309 mMessage,
00310 sFont,
00311 FALSE);
00312 text->setWordWrap(TRUE);
00313 text->setTabStop(FALSE);
00314 text->setMouseOpaque(FALSE);
00315 text->setBorderVisible(FALSE);
00316 text->setTakesNonScrollClicks(FALSE);
00317 text->setHideScrollbarForShortDocs(TRUE);
00318 text->setReadOnlyBgColor ( LLColor4::transparent );
00319
00320
00321 text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") );
00322 text->setEnabled(FALSE);
00323 text->setTabStop(FALSE);
00324 addChild(text);
00325
00326 if (mIsTip)
00327 {
00328
00329 LLChat chat(mMessage);
00330 chat.mSourceType = CHAT_SOURCE_SYSTEM;
00331 LLFloaterChat::getInstance(LLSD())->addChatHistory(chat);
00332 }
00333 else
00334 {
00335 LLButton* btn;
00336 btn = new LLButton("next",
00337 LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD),
00338 "notify_next.png",
00339 "notify_next.png",
00340 "",
00341 onClickNext,
00342 this,
00343 sFont);
00344 btn->setScaleImage(TRUE);
00345 btn->setToolTip(LLString("Next"));
00346 addChild(btn);
00347 mNextBtn = btn;
00348
00349
00350
00351 S32 btn_width = mIsCaution? 84 : 90;
00352 LLRect btn_rect;
00353
00354 for (S32 i = 0; i < mNumOptions; i++)
00355 {
00356 S32 index = i;
00357 S32 btn_height= BTN_HEIGHT;
00358 const LLFontGL* font = sFont;
00359 S32 ignore_pad = 0;
00360
00361 if (layout_script_dialog)
00362 {
00363
00364 index = i + 2;
00365 if (i == 0)
00366 {
00367
00368 btn_height = BTN_HEIGHT_SMALL;
00369 font = sFontSmall;
00370 ignore_pad = 10;
00371 }
00372 }
00373
00374 btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad,
00375 BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD),
00376 btn_width - 2*ignore_pad,
00377 btn_height);
00378
00379 InstanceAndS32* userdata = new InstanceAndS32;
00380 userdata->mSelf = this;
00381 userdata->mButton = i;
00382
00383 mBtnCallbackData.push_back(userdata);
00384
00385 btn = new LLButton(options[i], btn_rect, "", onClickButton, userdata);
00386 btn->setFont(font);
00387
00388 if (mIsCaution)
00389 {
00390 btn->setImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor"));
00391 btn->setDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor"));
00392 }
00393
00394 addChild(btn, -1);
00395
00396 if (i == mDefaultOption)
00397 {
00398 setDefaultBtn(btn);
00399 }
00400 }
00401
00402 sNotifyBoxCount++;
00403
00404
00405 if (sNotifyBoxCount == 1
00406 && mNextBtn)
00407 {
00408 mNextBtn->setVisible(FALSE);
00409 }
00410 }
00411 }
00412
00413
00414 LLNotifyBox::~LLNotifyBox()
00415 {
00416 delete mBehavior;
00417 mBehavior = NULL;
00418
00419 std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
00420
00421 if (mUnique)
00422 {
00423 sOpenUniqueNotifyBoxes.erase(getName() + mMessage);
00424 }
00425 }
00426
00427
00428 BOOL LLNotifyBox::handleMouseUp(S32 x, S32 y, MASK mask)
00429 {
00430 if (mIsTip)
00431 {
00432 if (mBehavior->mCallback)
00433 {
00434 mBehavior->mCallback(0, mBehavior->mData);
00435 mBehavior->mCallback = NULL;
00436 }
00437 close();
00438 return TRUE;
00439 }
00440
00441 setFocus(TRUE);
00442
00443 return LLPanel::handleMouseUp(x, y, mask);
00444 }
00445
00446
00447 BOOL LLNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
00448 {
00449 if (!mIsTip)
00450 {
00451 moveToBack(true);
00452 return TRUE;
00453 }
00454
00455 return LLPanel::handleRightMouseDown(x, y, mask);
00456 }
00457
00458
00459
00460 void LLNotifyBox::draw()
00461 {
00462
00463 if (gTeleportDisplay)
00464 {
00465 mEventTimer.stop();
00466 }
00467 else if (!mEventTimer.getStarted())
00468 {
00469 mEventTimer.start();
00470 }
00471
00472 F32 display_time = mAnimateTimer.getElapsedTimeF32();
00473
00474 if (mAnimating && display_time < ANIMATION_TIME)
00475 {
00476 glMatrixMode(GL_MODELVIEW);
00477 LLUI::pushMatrix();
00478
00479 S32 height = getRect().getHeight();
00480 F32 fraction = display_time / ANIMATION_TIME;
00481 F32 voffset = (1.f - fraction) * height;
00482 if (mIsTip) voffset *= -1.f;
00483 LLUI::translate(0.f, voffset, 0.f);
00484
00485 drawBackground();
00486
00487 LLPanel::draw();
00488
00489 LLUI::popMatrix();
00490 }
00491 else
00492 {
00493 if(mAnimating)
00494 {
00495 mAnimating = FALSE;
00496 if(!mIsTip)
00497 {
00498
00499 gNotifyBoxView->showOnly(this);
00500 }
00501 }
00502 drawBackground();
00503 LLPanel::draw();
00504 }
00505 }
00506
00507 void LLNotifyBox::drawBackground() const
00508 {
00509 LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga");
00510 if (imagep)
00511 {
00512 LLViewerImage::bindTexture(imagep->getImage());
00513
00514 LLColor4 color = mIsCaution? gColors.getColor("NotifyCautionBoxColor") : gColors.getColor("NotifyBoxColor");
00515 if(gFocusMgr.childHasKeyboardFocus( this ))
00516 {
00517 const S32 focus_width = 2;
00518 color = gColors.getColor("FloaterFocusBorderColor");
00519 gGL.color4fv(color.mV);
00520 gl_segmented_rect_2d_tex(-focus_width, getRect().getHeight() + focus_width,
00521 getRect().getWidth() + focus_width, -focus_width,
00522 imagep->getTextureWidth(), imagep->getTextureHeight(),
00523 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
00524 color = gColors.getColor("ColorDropShadow");
00525 gGL.color4fv(color.mV);
00526 gl_segmented_rect_2d_tex(0, getRect().getHeight(), getRect().getWidth(), 0, imagep->getTextureWidth(), imagep->getTextureHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
00527
00528 if( mIsCaution )
00529 color = gColors.getColor("NotifyCautionBoxColor");
00530 else
00531 color = gColors.getColor("NotifyBoxColor");
00532
00533 gGL.color4fv(color.mV);
00534 gl_segmented_rect_2d_tex(1, getRect().getHeight()-1, getRect().getWidth()-1, 1, imagep->getTextureWidth(), imagep->getTextureHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
00535 }
00536 else
00537 {
00538 gGL.color4fv(color.mV);
00539 gl_segmented_rect_2d_tex(0, getRect().getHeight(), getRect().getWidth(), 0, imagep->getTextureWidth(), imagep->getTextureHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
00540 }
00541 }
00542 }
00543
00544
00545 void LLNotifyBox::close()
00546 {
00547 BOOL isTipTmp = mIsTip;
00548
00549 if (!mIsTip)
00550 {
00551 sNotifyBoxCount--;
00552 }
00553
00554 die();
00555 if(!isTipTmp)
00556 {
00557 LLNotifyBox * front = gNotifyBoxView->getFirstNontipBox();
00558 if(front)
00559 {
00560 gNotifyBoxView->showOnly(front);
00561
00562
00563 if (front->getDefaultButton())
00564 {
00565 front->getDefaultButton()->setFocus(TRUE);
00566 }
00567 gFocusMgr.triggerFocusFlash();
00568 }
00569 }
00570 }
00571
00572 void LLNotifyBox::format(LLString& msg, const LLString::format_map_t& args)
00573 {
00574
00575 LLString::format_map_t targs = args;
00576 targs["[SECOND_LIFE]"] = "Second Life";
00577 LLString::format(msg, targs);
00578 }
00579
00580
00581
00582 BOOL LLNotifyBox::tick()
00583 {
00584 if (mIsTip)
00585 {
00586 close();
00587 }
00588 return FALSE;
00589 }
00590
00591 void LLNotifyBox::setVisible(BOOL visible)
00592 {
00593
00594 if(visible && !mIsTip)
00595 {
00596 mNextBtn->setVisible(sNotifyBoxCount > 1);
00597 mNextBtn->setEnabled(sNotifyBoxCount > 1);
00598 }
00599 LLPanel::setVisible(visible);
00600 }
00601
00602 void LLNotifyBox::moveToBack(bool getfocus)
00603 {
00604
00605 gNotifyBoxView->sendChildToBack(this);
00606 if(!mIsTip && mNextBtn)
00607 {
00608 mNextBtn->setVisible(FALSE);
00609
00610
00611 if (gNotifyBoxView->getChildCount() > 0)
00612 {
00613 LLNotifyBox* front = gNotifyBoxView->getFirstNontipBox();
00614 if (front)
00615 {
00616 gNotifyBoxView->showOnly(front);
00617 if (getfocus)
00618 {
00619
00620
00621 if (front->mNextBtn != NULL)
00622 {
00623 front->mNextBtn->setFocus(TRUE);
00624 }
00625 gFocusMgr.triggerFocusFlash();
00626 }
00627 }
00628 }
00629 }
00630 }
00631
00632
00633
00634 LLRect LLNotifyBox::getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution)
00635 {
00636 S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight");
00637 if (is_caution)
00638 {
00639
00640
00641
00642
00643 notify_height = gSavedSettings.getS32("PermissionsCautionNotifyBoxHeight");
00644 }
00645 const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
00646
00647 const S32 TOP = gNotifyBoxView->getRect().getHeight();
00648 const S32 RIGHT = gNotifyBoxView->getRect().getWidth();
00649 const S32 LEFT = RIGHT - NOTIFY_WIDTH;
00650
00651 if (num_options < 1)
00652 {
00653 num_options = 1;
00654 }
00655
00656
00657 if (layout_script_dialog)
00658 {
00659 num_options += 2;
00660 }
00661
00662 S32 additional_lines = (num_options-1) / 3;
00663
00664 notify_height += additional_lines * (BTN_HEIGHT + VPAD);
00665
00666 return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
00667 }
00668
00669
00670 LLRect LLNotifyBox::getNotifyTipRect(const LLString &utf8message)
00671 {
00672 S32 line_count = 1;
00673 LLWString message = utf8str_to_wstring(utf8message);
00674 S32 message_len = message.length();
00675
00676 const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
00677
00678 const S32 text_area_width = NOTIFY_WIDTH - HPAD * 4 - 32;
00679
00680 const llwchar* wchars = message.c_str();
00681 const llwchar* start = wchars;
00682 const llwchar* end;
00683 S32 total_drawn = 0;
00684 BOOL done = FALSE;
00685
00686 do
00687 {
00688 line_count++;
00689
00690 for (end=start; *end != 0 && *end != '\n'; end++)
00691 ;
00692
00693 if( *end == 0 )
00694 {
00695 end = wchars + message_len;
00696 done = TRUE;
00697 }
00698
00699 S32 remaining = end - start;
00700 while( remaining )
00701 {
00702 S32 drawn = sFont->maxDrawableChars( start, (F32)text_area_width, remaining, TRUE );
00703
00704 if( 0 == drawn )
00705 {
00706 drawn = 1;
00707 }
00708
00709 total_drawn += drawn;
00710 start += drawn;
00711 remaining -= drawn;
00712
00713 if( total_drawn < message_len )
00714 {
00715 if( (wchars[ total_drawn ] != '\n') )
00716 {
00717
00718 line_count++;
00719 }
00720 }
00721 else
00722 {
00723 done = TRUE;
00724 }
00725 }
00726
00727 total_drawn++;
00728 end++;
00729 start = end;
00730 } while( !done );
00731
00732 const S32 MIN_NOTIFY_HEIGHT = 72;
00733 const S32 MAX_NOTIFY_HEIGHT = 600;
00734 S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight());
00735 if(gOverlayBar)
00736 {
00737 notify_height += gOverlayBar->getBoundingRect().mTop;
00738 }
00739 else
00740 {
00741
00742
00743 notify_height += 10;
00744 }
00745 notify_height += VPAD;
00746 notify_height = llclamp(notify_height, MIN_NOTIFY_HEIGHT, MAX_NOTIFY_HEIGHT);
00747
00748 const S32 RIGHT = gNotifyBoxView->getRect().getWidth();
00749 const S32 LEFT = RIGHT - NOTIFY_WIDTH;
00750
00751
00752 return LLRect(LEFT, notify_height-1, RIGHT, -1);
00753 }
00754
00755
00756
00757 void LLNotifyBox::onClickButton(void* data)
00758 {
00759 InstanceAndS32* self_and_button = (InstanceAndS32*)data;
00760 LLNotifyBox* self = self_and_button->mSelf;
00761 S32 button = self_and_button->mButton;
00762
00763
00764
00765 if ((self->mIsCaution) && (button > 0) && (button == (self->mNumOptions - 1)))
00766 {
00767
00768 LLAlertDialog::showXml("DebitPermissionDetails");
00769
00770
00771 return;
00772 }
00773
00774 if (self->mBehavior->mCallback)
00775 {
00776 self->mBehavior->mCallback(button, self->mBehavior->mData);
00777 self->mBehavior->mCallback = NULL;
00778 }
00779
00780 self->close();
00781 }
00782
00783
00784
00785 void LLNotifyBox::onClickNext(void* data)
00786 {
00787 LLNotifyBox* self = static_cast<LLNotifyBox*>(data);
00788 self->moveToBack(true);
00789 }
00790
00791
00792 LLPointer<LLNotifyBoxTemplate> LLNotifyBox::getTemplate(const LLString& xml_desc)
00793 {
00794
00795
00796 if (!sDefaultTemplate)
00797 {
00798
00799 sDefaultTemplate = new LLNotifyBoxTemplate(FALSE, gSavedSettings.getF32("NotifyTipDuration"));
00800 sDefaultTemplate->addOption("OK", FALSE);
00801 }
00802
00803 LLPointer<LLNotifyBoxTemplate> xml_template;
00804 template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
00805 if (iter != sNotifyTemplates.end())
00806 {
00807 xml_template = iter->second;
00808 }
00809 else
00810 {
00811 LLString tmsg = "[Notification template not found:\n " + xml_desc + " ]";
00812 sDefaultTemplate->setMessage(tmsg);
00813 xml_template = sDefaultTemplate;
00814 }
00815
00816 return xml_template;
00817 }
00818
00819
00820
00821
00822 const LLString LLNotifyBox::getTemplateMessage(const LLString& xml_desc, const LLString::format_map_t& args)
00823 {
00824 template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
00825 if (iter != sNotifyTemplates.end())
00826 {
00827 LLString message = iter->second->mMessage;
00828 format(message, args);
00829 return message;
00830 }
00831 else
00832 {
00833 return xml_desc;
00834 }
00835 }
00836
00837
00838 const LLString LLNotifyBox::getTemplateMessage(const LLString& xml_desc)
00839 {
00840 template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
00841 if (iter != sNotifyTemplates.end())
00842 {
00843 return iter->second->mMessage;
00844 }
00845 else
00846 {
00847 return xml_desc;
00848 }
00849 }
00850
00851
00852 BOOL LLNotifyBox::getTemplateIsCaution(const LLString& xml_desc)
00853 {
00854 BOOL is_caution = FALSE;
00855
00856 template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
00857 if (iter != sNotifyTemplates.end())
00858 {
00859 is_caution = iter->second->mIsCaution;
00860 }
00861
00862 return is_caution;
00863 }
00864
00865
00866 bool LLNotifyBox::parseNotify(const LLString& xml_filename)
00867 {
00868 LLXMLNodePtr root;
00869
00870 BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
00871
00872 if (!success || root.isNull() || !root->hasName( "notifications" ))
00873 {
00874 llerrs << "Problem reading UI Notify file: " << xml_filename << llendl;
00875 return false;
00876 }
00877
00878 for (LLXMLNode* notify = root->getFirstChild();
00879 notify != NULL; notify = notify->getNextSibling())
00880 {
00881 if (!notify->hasName("notify"))
00882 {
00883 continue;
00884 }
00885
00886 BOOL unique = FALSE;
00887 notify->getAttributeBOOL("unique", unique);
00888
00889 F32 duration = gSavedSettings.getF32("NotifyTipDuration");
00890 notify->getAttributeF32("duration", duration);
00891
00892 LLPointer<LLNotifyBoxTemplate> xml_template = new LLNotifyBoxTemplate(unique, duration);
00893
00894
00895 LLString notify_name;
00896 if (notify->getAttributeString("name", notify_name))
00897 {
00898 xml_template->mLabel = notify_name;
00899 }
00900 else
00901 {
00902 llwarns << "Unable to parse notify with no name" << llendl;
00903 continue;
00904 }
00905
00906 BOOL tip;
00907 if (notify->getAttributeBOOL("tip", tip))
00908 {
00909 xml_template->mIsTip = tip;
00910 }
00911
00912
00913
00914 BOOL caution = FALSE;
00915 if (notify->getAttributeBOOL("caution", caution))
00916 {
00917 if (xml_template)
00918 {
00919 xml_template->mIsCaution = caution;
00920 }
00921 }
00922
00923
00924 S32 btn_idx = 0;
00925 for (LLXMLNode* child = notify->getFirstChild();
00926 child != NULL; child = child->getNextSibling())
00927 {
00928
00929 if (child->hasName("message"))
00930 {
00931 xml_template->mMessage = child->getTextContents();
00932 }
00933
00934
00935 if (child->hasName("option"))
00936 {
00937 LLString label = child->getValue();
00938 BOOL is_default = FALSE;
00939 child->getAttributeBOOL("default", is_default);
00940 LLString ignore_text;
00941 if (!child->getAttributeString("ignore", ignore_text))
00942 {
00943 ignore_text = label;
00944 }
00945 xml_template->addOption(label, is_default);
00946 btn_idx++;
00947 }
00948 }
00949
00950
00951 if (xml_template->mOptions.empty())
00952 {
00953 xml_template->addOption("OK", FALSE);
00954 }
00955 sNotifyTemplates[xml_template->mLabel] = xml_template;
00956 }
00957 return true;
00958 }
00959
00960 LLNotifyBoxView::LLNotifyBoxView(const LLString& name, const LLRect& rect, BOOL mouse_opaque, U32 follows)
00961 : LLUICtrl(name,rect,mouse_opaque,NULL,NULL,follows)
00962 {
00963 }
00964
00965 LLNotifyBox * LLNotifyBoxView::getFirstNontipBox() const
00966 {
00967
00968
00969 for(child_list_const_iter_t iter = getChildList()->begin();
00970 iter != getChildList()->end();
00971 iter++)
00972 {
00973
00974 LLView* view = *iter;
00975 if (view->getName() == "groupnotify")
00976 continue;
00977 LLNotifyBox* box = static_cast<LLNotifyBox*>(view);
00978 if(!box->isTip() && !box->isDead())
00979 {
00980 return box;
00981 }
00982 }
00983 return NULL;
00984 }
00985
00986 void LLNotifyBoxView::showOnly(LLView * view)
00987 {
00988 if(view)
00989 {
00990
00991 LLNotifyBox * shown = static_cast<LLNotifyBox*>(view);
00992
00993 for(child_list_const_iter_t iter = getChildList()->begin();
00994 iter != getChildList()->end();
00995 iter++)
00996 {
00997 LLNotifyBox * box = static_cast<LLNotifyBox*>(*iter);
00998 if(box != view && box->getVisible() && !box->isTip())
00999 {
01000 box->setVisible(FALSE);
01001 }
01002 }
01003 shown->setVisible(TRUE);
01004 sendChildToFront(shown);
01005 }
01006 }
01007
01008 void LLNotifyBoxView::purgeMessagesMatching(const Matcher& matcher)
01009 {
01010
01011
01012 LLView::child_list_t notification_queue(*getChildList());
01013 for(LLView::child_list_iter_t iter = notification_queue.begin();
01014 iter != notification_queue.end();
01015 iter++)
01016 {
01017 LLNotifyBox* notification = (LLNotifyBox*)*iter;
01018 if(matcher.matches(notification->getNotifyCallback(), notification->getUserData()))
01019 {
01020 removeChild(notification);
01021 }
01022 }
01023 }