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