aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llalertdialog.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llui/llalertdialog.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llui/llalertdialog.cpp')
-rw-r--r--linden/indra/llui/llalertdialog.cpp829
1 files changed, 829 insertions, 0 deletions
diff --git a/linden/indra/llui/llalertdialog.cpp b/linden/indra/llui/llalertdialog.cpp
new file mode 100644
index 0000000..861bbc6
--- /dev/null
+++ b/linden/indra/llui/llalertdialog.cpp
@@ -0,0 +1,829 @@
1/**
2 * @file llalertdialog.cpp
3 * @brief LLAlertDialog base class
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29
30#include "llboost.h"
31
32#include "llalertdialog.h"
33#include "llfontgl.h"
34#include "llresmgr.h"
35#include "lltextbox.h"
36#include "llbutton.h"
37#include "llcheckboxctrl.h"
38#include "llkeyboard.h"
39#include "llfocusmgr.h"
40#include "llui.h"
41#include "llxmlnode.h"
42#include "lllineeditor.h"
43#include "lluictrlfactory.h"
44
45
46const S32 MAX_ALLOWED_MSG_WIDTH = 400;
47const F32 DEFAULT_BUTTON_DELAY = 0.5f;
48const S32 MSG_PAD = 8;
49
50/*static*/ LLAlertDialog::template_map_t LLAlertDialog::sAlertTemplates;
51/*static*/ LLAlertDialog::template_map_t LLAlertDialog::sIgnorableTemplates;
52/*static*/ LLControlGroup* LLAlertDialog::sSettings = NULL;
53/*static*/ std::map<LLString,LLAlertDialog*> LLAlertDialog::sUniqueActiveMap;
54/*static*/ LLAlertDialog::display_callback_t LLAlertDialog::sDisplayCallback;
55
56//static
57LLAlertDialog* LLAlertDialog::createXml( const LLString& xml_desc,
58 alert_callback_t callback, void *user_data)
59{
60 LLString::format_map_t args;
61 return createXml(xml_desc, args, callback, user_data);
62}
63
64//static
65LLAlertDialog* LLAlertDialog::createXml( const LLString& xml_desc, const LLString::format_map_t& args,
66 alert_callback_t callback, void *user_data)
67{
68 template_map_t::iterator iter = sAlertTemplates.find(xml_desc);
69 if (iter != sAlertTemplates.end())
70 {
71 LLAlertDialogTemplate* xml_template = iter->second;
72 // deletes itself
73 llwarns << "Alert: [" << xml_desc << "] " << llendl;
74 LLAlertDialog* dialog = new LLAlertDialog( xml_template, args, callback, user_data);
75 return dialog;
76 }
77 else
78 {
79 LLString::format_map_t args;
80 args["[ALERT_NAME]"] = xml_desc;
81 llwarns << "Missing Alert: [" << xml_desc << "]" << llendl;
82 LLAlertDialog* dialogp = LLAlertDialog::showXml("MissingAlert", args);
83 if (dialogp == NULL)
84 {
85 llerrs << "Bad or missing alerts.xml!" << llendl;
86 }
87 return NULL;
88 }
89}
90
91//static
92LLAlertDialog* LLAlertDialog::showXml( const LLString& xml_desc,
93 alert_callback_t callback, void *user_data)
94{
95 LLString::format_map_t args;
96 return showXml(xml_desc, args, callback, user_data);
97}
98
99//static
100LLAlertDialog* LLAlertDialog::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
101 alert_callback_t callback, void *user_data)
102{
103 LLAlertDialog* dialog = createXml(xml_desc, args, callback, user_data);
104 return dialog && dialog->show() ? dialog : NULL;
105}
106
107//static
108LLAlertDialog* LLAlertDialog::showCritical( const LLString& desc, alert_callback_t callback, void *user_data)
109{
110 LLAlertDialogTemplate xml_template;
111 LLString::format_map_t args;
112 xml_template.mTitle = "Critical Error";
113 xml_template.mMessage = desc;
114 xml_template.mModal = TRUE;
115 xml_template.mOptions.push_back("Quit");
116 LLAlertDialog* dialog = new LLAlertDialog( &xml_template, args, callback, user_data);
117 return dialog && dialog->show() ? dialog : NULL;
118}
119
120//-----------------------------------------------------------------------------
121// Private methods
122
123static const S32 VPAD = 16;
124static const S32 HPAD = 25;
125static const S32 BTN_HPAD = 8;
126static const LLFONT_ID font_name = LLFONT_SANSSERIF;
127
128LLAlertDialog::LLAlertDialog( const LLAlertDialogTemplate* xml_template,
129 const LLString::format_map_t& args,
130 alert_callback_t callback, void *user_data)
131 : LLModalDialog( xml_template->mTitle, 100, 100, xml_template->mModal ), // dummy size. Will reshape below.
132 mCallback( callback ),
133 mUserData( user_data ),
134 mNumOptions( 0 ),
135 mDefaultOption( 0 ),
136 mOptionChosen( -1 ),
137 mCheck(NULL),
138 mUnique(xml_template->mUnique),
139 mIgnorable(xml_template->mIgnorable),
140 mLabel(xml_template->mLabel),
141 mIgnoreLabel(xml_template->mIgnoreLabel),
142 mButtonData(NULL),
143 mLineEditor(NULL),
144 mTextCallback(NULL)
145{
146 createDialog(&(xml_template->mOptions), xml_template->mDefaultOption,
147 xml_template->mMessage, args,
148 xml_template->mEditLineText);
149 setTitle(xml_template->mTitle);
150 if (xml_template->mIgnorable)
151 {
152 //XUI:translate!
153 LLString msg;
154 if (xml_template->mIgnorable == IGNORE_USE_DEFAULT)
155 {
156 msg = "Skip this dialog next time";
157 }
158 else // xml_template->mIgnorable == IGNORE_USE_SAVED
159 {
160 msg = "Always choose this option";
161 }
162 setCheckBox(msg, xml_template->mIgnoreLabel);
163 }
164}
165
166// All logic for deciding not to show an alert is done here,
167// so that the alert is valid until show() is called.
168bool LLAlertDialog::show()
169{
170 // If mModal, check to see if we are not displaying alerts,
171 // and do any application logic before showing modal alerts
172 if (sDisplayCallback)
173 {
174 bool show = sDisplayCallback(mModal);
175 if (show == false)
176 {
177 mOptionChosen = mDefaultOption;
178 llinfos << "Alert: " << mLabel << llendl;
179 delete this;
180 return false;
181 }
182 }
183
184 // Check to see if the user wants to ignore this alert
185 if (mIgnorable > 0)
186 {
187 BOOL warn = sSettings->getWarning(mIgnoreLabel);
188 if (!warn)
189 {
190 switch(mIgnorable)
191 {
192 case IGNORE_USE_DEFAULT:
193 mOptionChosen = mDefaultOption;
194 break;
195 case IGNORE_USE_SAVED:
196 mOptionChosen = sSettings->getS32("Default" + mIgnoreLabel);
197 break;
198 case IGNORE_SHOW_AGAIN:
199 break;
200 }
201 delete this;
202 return false;
203 }
204 }
205
206 // Check to see if we are already displaying the alert
207 if (mUnique)
208 {
209 std::map<LLString,LLAlertDialog*>::iterator iter = sUniqueActiveMap.find(mLabel);
210 if (iter != sUniqueActiveMap.end())
211 {
212 gFloaterView->bringToFront(iter->second);
213 mUnique = FALSE; // don't remove entry from map on destruction
214 delete this;
215 return false;
216 }
217 sUniqueActiveMap[mLabel] = this;
218 }
219 startModal();
220 gFloaterView->adjustToFitScreen(this, FALSE);
221 open();
222 setFocus(TRUE);
223 if (mLineEditor)
224 {
225 mLineEditor->setFocus(TRUE);
226 mLineEditor->selectAll();
227 }
228 if(mDefaultOption >= 0)
229 {
230 // delay before enabling default button
231 mDefaultBtnTimer.start();
232 mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
233 }
234 return true;
235}
236
237//static
238void LLAlertDialog::format(LLString& msg, const LLString::format_map_t& args)
239{
240 // XUI:translate!
241 LLString::format_map_t targs = args;
242 targs["[SECOND_LIFE]"] = "Second Life";
243 LLString::format(msg, targs);
244}
245
246void LLAlertDialog::createDialog(const std::vector<LLString>* optionsp, S32 default_option,
247 const LLString& msg_in, const LLString::format_map_t& args,
248 const LLString& edit_text)
249{
250 setBackgroundVisible(TRUE);
251 setBackgroundOpaque(TRUE);
252
253 const LLFontGL* font = gResMgr->getRes( font_name );
254 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
255 const S32 EDITOR_HEIGHT = 20;
256
257 // buttons
258 std::vector<LLString> default_option_list;
259
260 mNumOptions = optionsp->size();
261
262 if( 0 == mNumOptions )
263 {
264 default_option_list.push_back("Close");
265 optionsp = &default_option_list;
266 default_option = 0;
267 mNumOptions = 1;
268 }
269
270 const std::vector<LLString>& options = *optionsp;
271
272 mButtonData = new ButtonData[mNumOptions];
273
274 // Calc total width of buttons
275 S32 button_width = 0;
276 S32 sp = font->getWidth("OO");
277 for( S32 i = 0; i < mNumOptions; i++ )
278 {
279 S32 w = S32(font->getWidth( options[i] ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
280 button_width = llmax( w, button_width );
281 }
282 S32 btn_total_width = button_width;
283 if( mNumOptions > 1 )
284 {
285 btn_total_width = (mNumOptions * button_width) + ((mNumOptions - 1) * BTN_HPAD);
286 }
287
288 // Split message into lines, separated by '\n'
289 LLString msg = msg_in;
290 LLAlertDialog::format(msg, args);
291
292 llwarns << "Alert: " << msg << llendl;
293
294 S32 max_msg_width = 0;
295 std::vector<LLString> msg_lines;
296
297 boost_tokenizer tokens(msg, boost::char_separator<char>("\n"));
298 for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
299 {
300 LLString line(*token_iter);
301 boost_tokenizer line_toks(line, boost::char_separator<char>(" \t"));
302 LLString cur_line;
303 S32 cur_line_width = 0;
304 for (boost_tokenizer::iterator token_iter2 = line_toks.begin(); token_iter2 != line_toks.end(); ++token_iter2)
305 {
306 LLString tok(*token_iter2);
307 LLString word;
308 if (cur_line_width > 0)
309 {
310 word = " ";
311 }
312 word += tok;
313 S32 word_width = S32(font->getWidth( word ) + 0.99f);
314 if (cur_line_width > 0 && cur_line_width + word_width > MAX_ALLOWED_MSG_WIDTH)
315 {
316 max_msg_width = llmax( max_msg_width, cur_line_width + MSG_PAD);
317 msg_lines.push_back( cur_line );
318 cur_line.clear();
319 cur_line_width = 0;
320 word = tok; // no ' '
321 }
322 cur_line += word;
323 cur_line_width += word_width;
324 }
325 if (cur_line_width > 0)
326 {
327 max_msg_width = llmax( max_msg_width, cur_line_width );
328 msg_lines.push_back( cur_line );
329 }
330 }
331
332 // pad message box so we don't clip last character
333 max_msg_width += 2;
334
335 S32 dialog_width = llmax( btn_total_width, max_msg_width ) + 2 * HPAD;
336 S32 dialog_height = LINE_HEIGHT * msg_lines.size() + 3 * VPAD + BTN_HEIGHT;
337
338 if (hasTitleBar())
339 {
340 dialog_height += LINE_HEIGHT; // room for title bar
341 }
342
343 if (edit_text.size() > 0)
344 {
345 dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f));
346 dialog_height += EDITOR_HEIGHT;
347 }
348
349 reshape( dialog_width, dialog_height, FALSE );
350
351 // Message
352 S32 msg_x = (mRect.getWidth() - max_msg_width) / 2;
353 S32 msg_y = mRect.getHeight() - VPAD - LINE_HEIGHT;
354 if (hasTitleBar())
355 {
356 msg_y -= LINE_HEIGHT; // room for title
357 }
358
359 for( std::vector<LLString>::iterator iter = msg_lines.begin(); iter != msg_lines.end(); ++iter )
360 {
361 LLRect msg_rect;
362 msg_rect.setOriginAndSize( msg_x, msg_y, max_msg_width, LINE_HEIGHT );
363 LLTextBox* label_box = new LLTextBox( "Alert message", msg_rect, iter->c_str(), font );
364 label_box->setColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) );
365 addChild(label_box);
366 msg_y -= LINE_HEIGHT;
367 }
368
369 // Buttons
370 S32 button_left = (mRect.getWidth() - btn_total_width) / 2;
371
372 for( S32 i = 0; i < mNumOptions; i++ )
373 {
374 LLRect button_rect;
375 button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT );
376
377 LLButton* btn = new LLButton(
378 "btn", button_rect,
379 "","", "",
380 &LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i]),
381 font,
382 options[i],
383 options[i]);
384
385 mButtonData[i].mSelf = this;
386 mButtonData[i].mButton = btn;
387 mButtonData[i].mOption = i;
388
389 addChild(btn);
390
391 if( i == default_option )
392 {
393 btn->setFocus(TRUE);
394 }
395
396 button_left += button_width + BTN_HPAD;
397 }
398
399 // (Optional) Edit Box
400 if (edit_text.size() > 0)
401 {
402 S32 y = VPAD + BTN_HEIGHT + VPAD/2;
403 mLineEditor = new LLLineEditor("lineeditor",
404 LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y),
405 edit_text,
406 LLFontGL::sSansSerif,
407 STD_STRING_STR_LEN);
408 addChild(mLineEditor);
409 }
410
411}
412
413bool LLAlertDialog::setCheckBox( const LLString& check_title, const LLString& check_control )
414{
415 const LLFontGL* font = gResMgr->getRes( font_name );
416 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
417
418 // Extend dialog for "check next time"
419 S32 max_msg_width = mRect.getWidth() - 2 * HPAD;
420 S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16;
421 max_msg_width = llmax(max_msg_width, check_width);
422 S32 dialog_width = max_msg_width + 2 * HPAD;
423
424 S32 dialog_height = mRect.getHeight();
425 dialog_height += LINE_HEIGHT;
426 dialog_height += LINE_HEIGHT / 2;
427
428 reshape( dialog_width, dialog_height, FALSE );
429
430 S32 msg_x = (mRect.getWidth() - max_msg_width) / 2;
431
432 LLRect check_rect;
433 check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2,
434 max_msg_width, LINE_HEIGHT);
435
436 mCheck = new LLCheckboxCtrl("check", check_rect, check_title, font);
437 addChild(mCheck);
438
439 // mCheck is sometimes "show again" and sometimes "hide" :-(
440 // If it's "Show Again", and we showed it, it must be checked. JC
441 if (mIgnorable == IGNORE_SHOW_AGAIN)
442 {
443 mCheck->setValue(TRUE);
444 }
445
446 return true;
447}
448
449void LLAlertDialog::setVisible( BOOL visible )
450{
451 LLModalDialog::setVisible( visible );
452
453 if( visible )
454 {
455 centerOnScreen();
456 make_ui_sound("UISndAlert");
457 }
458}
459
460LLAlertDialog::~LLAlertDialog()
461{
462 if (mOptionChosen >= 0)
463 {
464 if (mTextCallback && mLineEditor)
465 {
466 mTextCallback(mOptionChosen, mLineEditor->getText(), mUserData);
467 }
468 else if (mCallback)
469 {
470 mCallback(mOptionChosen, mUserData);
471 }
472
473 // Only change warn state if we actually warned.
474 if (mCheck
475 && sSettings->getWarning(mIgnoreLabel))
476 {
477 // mCheck sometimes means "hide and do the default" and
478 // other times means "warn me again". Yuck. JC
479 BOOL check = mCheck->getValue();
480 switch(mIgnorable)
481 {
482 case IGNORE_USE_DEFAULT:
483 sSettings->setWarning(mIgnoreLabel, !check);
484 break;
485 case IGNORE_USE_SAVED:
486 sSettings->setWarning(mIgnoreLabel, !check);
487 sSettings->setS32("Default" + mIgnoreLabel, mOptionChosen);
488 break;
489 case IGNORE_SHOW_AGAIN:
490 sSettings->setWarning(mIgnoreLabel, check);
491 break;
492 default:
493 break;
494 }
495 }
496 }
497 delete[] mButtonData;
498 if (mUnique)
499 {
500 sUniqueActiveMap.erase(mLabel);
501 }
502}
503
504BOOL LLAlertDialog::hasTitleBar() const
505{
506 return (getTitle() != "" && getTitle() != " ") // has title
507 || isMinimizeable()
508 || isCloseable();
509}
510
511BOOL LLAlertDialog::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
512{
513 if( KEY_RETURN == key && mask == MASK_NONE )
514 {
515 // Warning: handleKeyHere may result in the default button
516 // being committed, which will destroy this object.
517 // Everything works, but the call stack will pass through
518 // the very end of functions that belong to deleted objects.
519 // Should find a less fragile way to do this.
520 LLModalDialog::handleKeyHere( key, mask , called_from_parent );
521 return TRUE;
522 }
523 else if (KEY_RIGHT == key)
524 {
525 focusNextItem(FALSE);
526 return TRUE;
527 }
528 else if (KEY_LEFT == key)
529 {
530 focusPrevItem(FALSE);
531 return TRUE;
532 }
533 else if (KEY_TAB == key && mask == MASK_NONE)
534 {
535 focusNextItem(FALSE);
536 return TRUE;
537 }
538 else if (KEY_TAB == key && mask == MASK_SHIFT)
539 {
540 focusPrevItem(FALSE);
541 return TRUE;
542 }
543 else
544 {
545 return LLModalDialog::handleKeyHere( key, mask , called_from_parent );
546 }
547}
548
549// virtual
550void LLAlertDialog::draw()
551{
552 // if the default button timer has just expired, activate the default button
553 if(mDefaultBtnTimer.hasExpired() && mDefaultBtnTimer.getStarted())
554 {
555 mDefaultBtnTimer.stop(); // prevent this block from being run more than once
556 setDefaultBtn(mButtonData[mDefaultOption].mButton);
557 }
558 if (getVisible())
559 {
560 LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow");
561 S32 shadow_lines = LLUI::sConfigGroup->getS32("DropShadowFloater");
562
563 gl_drop_shadow( 0, mRect.getHeight(), mRect.getWidth(), 0,
564 shadow_color, shadow_lines);
565
566 LLModalDialog::draw();
567 }
568}
569
570void LLAlertDialog::setOptionEnabled( S32 option, BOOL enable )
571{
572 if( (option >= 0) && (option < mNumOptions) )
573 {
574 mButtonData[option].mButton->setEnabled( enable );
575 }
576}
577
578void LLAlertDialog::setEditTextCallback(alert_text_callback_t callback, void *user_data)
579{
580 if (mLineEditor)
581 {
582 mTextCallback = callback;
583 mUserData = user_data;
584 }
585 else
586 {
587 llwarns << "LLAlertDialog::setEditTextCallback called on dialog with no line editor" << llendl;
588 }
589}
590
591void LLAlertDialog::setEditTextArgs(const LLString::format_map_t& edit_args)
592{
593 if (mLineEditor)
594 {
595 LLString msg = mLineEditor->getText();
596 LLAlertDialog::format(msg, edit_args);
597 mLineEditor->setText(msg);
598 }
599 else
600 {
601 llwarns << "LLAlertDialog::setEditTextArgs called on dialog with no line editor" << llendl;
602 }
603}
604
605void LLAlertDialog::setDrawAsterixes(BOOL enable)
606{
607 if (mLineEditor)
608 {
609 if (enable)
610 {
611 mLineEditor->clear();
612 }
613 mLineEditor->setDrawAsterixes(enable);
614 }
615}
616
617// static
618void LLAlertDialog::onButtonPressed( void* userdata )
619{
620 ButtonData* button_data = (ButtonData*)userdata;
621 LLAlertDialog* self = button_data->mSelf;
622
623 self->mOptionChosen = button_data->mOption;
624 self->close(); // deletes self
625}
626
627//=============================================================================
628
629//static
630const LLString& LLAlertDialog::getTemplateMessage(const LLString& xml_desc)
631{
632 template_map_t::iterator iter = sAlertTemplates.find(xml_desc);
633 if (iter != sAlertTemplates.end())
634 {
635 return iter->second->mMessage;
636 }
637 else
638 {
639 return xml_desc;
640 }
641}
642
643//static
644bool LLAlertDialog::parseAlerts(const LLString& xml_filename, LLControlGroup* settings, BOOL settings_only)
645{
646 LLXMLNodePtr root;
647 BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
648
649 if (!success || root.isNull() || !root->hasName( "alerts" ))
650 {
651 llerrs << "Problem reading UI Alerts file: " << xml_filename << llendl;
652 return false;
653 }
654
655 BOOL add_settings = FALSE;
656 if (settings)
657 {
658 sSettings = settings;
659 add_settings = TRUE;
660 }
661 llassert(sSettings);
662
663 for (LLXMLNode* alert = root->getFirstChild();
664 alert != NULL; alert = alert->getNextSibling())
665 {
666 if (!alert->hasName("alert"))
667 {
668 continue;
669 }
670
671 LLAlertDialogTemplate* xml_template = settings_only ? NULL : new LLAlertDialogTemplate;
672
673 // name=
674 LLString alert_name;
675 if (alert->getAttributeString("name", alert_name))
676 {
677 if (xml_template)
678 {
679 xml_template->mLabel = alert_name;
680 }
681 }
682 else
683 {
684 llwarns << "Unable to parse alert with no name" << llendl;
685 delete xml_template;
686 continue;
687 }
688 // title=
689 LLString title;
690 if (alert->getAttributeString("title", title))
691 {
692 if (xml_template)
693 {
694 xml_template->mTitle = title;
695 }
696 }
697 // modal=
698 BOOL modal;
699 if (alert->getAttributeBOOL("modal", modal))
700 {
701 if (xml_template)
702 {
703 xml_template->mModal = modal;
704 }
705 }
706 // unique=
707 BOOL unique;
708 if (alert->getAttributeBOOL("unique", unique))
709 {
710 if (xml_template)
711 {
712 xml_template->mUnique = unique;
713 }
714 }
715
716 S32 default_option = 0;
717 BOOL nodefault;
718 if (alert->getAttributeBOOL("nodefault", nodefault))
719 {
720 if (nodefault)
721 {
722 if (xml_template)
723 {
724 xml_template->mDefaultOption = -1;
725 }
726 default_option = -1;
727 }
728 }
729
730 S32 btn_idx = 0;
731 for (LLXMLNode* child = alert->getFirstChild();
732 child != NULL; child = child->getNextSibling())
733 {
734 // <message>
735 if (child->hasName("message"))
736 {
737 if (xml_template)
738 {
739 xml_template->mMessage = child->getTextContents();
740 }
741 }
742
743 // <option>
744 if (child->hasName("option"))
745 {
746 LLString label = child->getTextContents();
747 BOOL is_default = FALSE;
748 child->getAttributeBOOL("default", is_default);
749 LLString ignore_text;
750 if (!child->getAttributeString("ignore", ignore_text))
751 {
752 ignore_text = label;
753 }
754 if (xml_template)
755 {
756 xml_template->addOption(label, ignore_text, is_default);
757 }
758 if (is_default)
759 {
760 default_option = btn_idx;
761 }
762 btn_idx++;
763 }
764
765 // <editline>
766 if (child->hasName("editline"))
767 {
768 if (xml_template)
769 {
770 xml_template->mEditLineText = child->getTextContents();
771 if (xml_template->mEditLineText.empty())
772 {
773 xml_template->mEditLineText = " ";
774 }
775 }
776 }
777
778 // <ignore>
779 if (child->hasName("ignore"))
780 {
781 LLString ignore_text = child->getTextContents();
782 // label=
783 LLString name;
784 child->getAttributeString("name", name);
785 if (name.empty())
786 {
787 name = alert_name;
788 }
789 if (xml_template)
790 {
791 xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_DEFAULT;
792 xml_template->mIgnoreListText = ignore_text;
793 xml_template->mIgnoreLabel = name;
794 }
795 if (!ignore_text.empty())
796 {
797 if (add_settings)
798 {
799 settings->addWarning(name);
800 }
801 if (xml_template)
802 {
803 sIgnorableTemplates[name] = xml_template; // will override any previous entry
804 }
805 }
806 // save_option=
807 BOOL save_option = FALSE;
808 child->getAttributeBOOL("save_option", save_option);
809 if (save_option)
810 {
811 if (xml_template)
812 {
813 xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_SAVED;
814 }
815 if (add_settings)
816 {
817 settings->declareS32("Default" + name, default_option, "Default option number for this alert dialog");
818 }
819 }
820 }
821 }
822 if (xml_template)
823 {
824 xml_template->mDefaultOption = default_option;
825 sAlertTemplates[xml_template->mLabel] = xml_template;
826 }
827 }
828 return true;
829}