aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llalertdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llui/llalertdialog.cpp')
-rw-r--r--linden/indra/llui/llalertdialog.cpp766
1 files changed, 212 insertions, 554 deletions
diff --git a/linden/indra/llui/llalertdialog.cpp b/linden/indra/llui/llalertdialog.cpp
index 80e54b6..f321db8 100644
--- a/linden/indra/llui/llalertdialog.cpp
+++ b/linden/indra/llui/llalertdialog.cpp
@@ -1,5 +1,4 @@
1/** 1/* @file llalertdialog.cpp
2 * @file llalertdialog.cpp
3 * @brief LLAlertDialog base class 2 * @brief LLAlertDialog base class
4 * 3 *
5 * $LicenseInfo:firstyear=2001&license=viewergpl$ 4 * $LicenseInfo:firstyear=2001&license=viewergpl$
@@ -17,7 +16,8 @@
17 * There are special exceptions to the terms and conditions of the GPL as 16 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 17 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 18 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception 19 * online at
20 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -46,85 +46,55 @@
46#include "llxmlnode.h" 46#include "llxmlnode.h"
47#include "lllineeditor.h" 47#include "lllineeditor.h"
48#include "lluictrlfactory.h" 48#include "lluictrlfactory.h"
49 49#include "llnotifications.h"
50#include "llfunctorregistry.h"
50 51
51const S32 MAX_ALLOWED_MSG_WIDTH = 400; 52const S32 MAX_ALLOWED_MSG_WIDTH = 400;
52const F32 DEFAULT_BUTTON_DELAY = 0.5f; 53const F32 DEFAULT_BUTTON_DELAY = 0.5f;
53const S32 MSG_PAD = 8; 54const S32 MSG_PAD = 8;
54 55
55/*static*/ LLAlertDialog::template_map_t LLAlertDialog::sAlertTemplates;
56/*static*/ LLAlertDialog::template_map_t LLAlertDialog::sIgnorableTemplates;
57/*static*/ LLControlGroup* LLAlertDialog::sSettings = NULL; 56/*static*/ LLControlGroup* LLAlertDialog::sSettings = NULL;
58/*static*/ std::map<std::string,LLAlertDialog*> LLAlertDialog::sUniqueActiveMap;
59/*static*/ LLAlertDialog::display_callback_t LLAlertDialog::sDisplayCallback;
60/*static*/ std::string LLAlertDialog::sStringSkipNextTime("Skip this dialog next time");
61/*static*/ std::string LLAlertDialog::sStringAlwaysChoose("Always choose this option");
62/*static*/ LLAlertDialog::URLLoader* LLAlertDialog::sURLLoader; 57/*static*/ LLAlertDialog::URLLoader* LLAlertDialog::sURLLoader;
63 58
64
65//static 59//static
66LLAlertDialog* LLAlertDialog::createXml( const std::string& xml_desc, 60void LLAlertDialog::initClass()
67 alert_callback_t callback, void *user_data)
68{ 61{
69 LLStringUtil::format_map_t args; 62 LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
70 return createXml(xml_desc, args, callback, user_data); 63 LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
64 LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&onNewNotification, _1, false));
65 LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&onNewNotification, _1, true));
71} 66}
72 67
73//static 68//static
74LLAlertDialog* LLAlertDialog::createXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, 69bool LLAlertDialog::onNewNotification(const LLSD& notify, bool is_modal)
75 alert_callback_t callback, void *user_data)
76{ 70{
77 template_map_t::iterator iter = sAlertTemplates.find(xml_desc); 71 LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
78 if (iter != sAlertTemplates.end()) 72
79 { 73 if(notification)
80 LLAlertDialogTemplate* xml_template = iter->second;
81 // deletes itself
82 llwarns << "Alert: [" << xml_desc << "] " << llendl;
83 LLAlertDialog* dialog = new LLAlertDialog( xml_template, args, callback, user_data);
84 return dialog;
85 }
86 else
87 { 74 {
88 LLStringUtil::format_map_t args; 75 if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load")
89 args["[ALERT_NAME]"] = xml_desc;
90 llwarns << "Missing Alert: [" << xml_desc << "]" << llendl;
91 LLAlertDialog* dialogp = LLAlertDialog::showXml("MissingAlert", args);
92 if (dialogp == NULL)
93 { 76 {
94 llerrs << "Bad or missing alerts.xml!" << llendl; 77 LLAlertDialog* dialog = new LLAlertDialog(notification, is_modal);
78 dialog->show();
79 }
80 else if (notify["sigtype"].asString() == "change")
81 {
82 LLAlertDialog* dialog = getInstance(notification->getID());
83 if (dialog)
84 {
85 dialog->show();
86 }
87 else
88 {
89 LLAlertDialog* dialog = new LLAlertDialog(notification, is_modal);
90 dialog->show();
91 }
95 } 92 }
96 return NULL;
97 } 93 }
98}
99
100//static
101LLAlertDialog* LLAlertDialog::showXml( const std::string& xml_desc,
102 alert_callback_t callback, void *user_data)
103{
104 LLStringUtil::format_map_t args;
105 return showXml(xml_desc, args, callback, user_data);
106}
107 94
108//static 95 return false;
109LLAlertDialog* LLAlertDialog::showXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args,
110 alert_callback_t callback, void *user_data)
111{
112 LLAlertDialog* dialog = createXml(xml_desc, args, callback, user_data);
113 return dialog && dialog->show() ? dialog : NULL;
114} 96}
115 97
116//static
117LLAlertDialog* LLAlertDialog::showCritical( const std::string& desc, alert_callback_t callback, void *user_data)
118{
119 LLAlertDialogTemplate xml_template;
120 LLStringUtil::format_map_t args;
121 xml_template.mTitle = "Critical Error";
122 xml_template.mMessage = desc;
123 xml_template.mModal = TRUE;
124 xml_template.mOptions.push_back("Quit");
125 LLAlertDialog* dialog = new LLAlertDialog( &xml_template, args, callback, user_data);
126 return dialog && dialog->show() ? dialog : NULL;
127}
128 98
129//----------------------------------------------------------------------------- 99//-----------------------------------------------------------------------------
130// Private methods 100// Private methods
@@ -132,183 +102,110 @@ LLAlertDialog* LLAlertDialog::showCritical( const std::string& desc, alert_callb
132static const S32 VPAD = 16; 102static const S32 VPAD = 16;
133static const S32 HPAD = 25; 103static const S32 HPAD = 25;
134static const S32 BTN_HPAD = 8; 104static const S32 BTN_HPAD = 8;
135static const LLFONT_ID font_name = LLFONT_SANSSERIF; 105static const LLFONT_ID FONT_NAME = LLFONT_SANSSERIF;
136 106
137LLAlertDialog::LLAlertDialog( const LLAlertDialogTemplate* xml_template, 107LLAlertDialog::LLAlertDialog( LLNotificationPtr notification, bool modal)
138 const LLStringUtil::format_map_t& args, 108 : LLModalDialog( notification->getLabel(), 100, 100, modal ), // dummy size. Will reshape below.
139 alert_callback_t callback, void *user_data) 109 LLInstanceTracker<LLAlertDialog, LLUUID>(notification->getID()),
140 : LLModalDialog( xml_template->mTitle, 100, 100, xml_template->mModal ), // dummy size. Will reshape below.
141 mCallback( callback ),
142 mUserData( user_data ),
143 mNumOptions( 0 ),
144 mDefaultOption( 0 ), 110 mDefaultOption( 0 ),
145 mOptionChosen( -1 ),
146 mCheck(NULL), 111 mCheck(NULL),
147 mCaution(xml_template->mCaution), 112 mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
148 mUnique(xml_template->mUnique), 113 mLabel(notification->getName()),
149 mIgnorable(xml_template->mIgnorable),
150 mLabel(xml_template->mLabel),
151 mIgnoreLabel(xml_template->mIgnoreLabel),
152 mButtonData(NULL),
153 mLineEditor(NULL), 114 mLineEditor(NULL),
154 mTextCallback(NULL), 115 mNote(notification)
155 mURLOption(0)
156{ 116{
157 mURL = xml_template->mURL; 117 const LLFontGL* font = LLResMgr::getInstance()->getRes( FONT_NAME );
158 mURLOption = xml_template->mURLOption; 118 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
159 createDialog(xml_template->mOptions, xml_template->mDefaultOption, 119 const S32 EDITOR_HEIGHT = 20;
160 xml_template->mMessage, args,
161 xml_template->mEditLineText);
162 setTitle(xml_template->mTitle);
163 if (xml_template->mIgnorable)
164 {
165 if (xml_template->mIgnorable == IGNORE_USE_DEFAULT)
166 {
167 setCheckBox(sStringSkipNextTime, xml_template->mIgnoreLabel);
168 }
169 else // xml_template->mIgnorable == IGNORE_USE_SAVED
170 {
171 setCheckBox(sStringAlwaysChoose, xml_template->mIgnoreLabel);
172 }
173 }
174}
175 120
176// All logic for deciding not to show an alert is done here, 121 LLNotificationFormPtr form = mNote->getForm();
177// so that the alert is valid until show() is called. 122 std::string edit_text_name;
178bool LLAlertDialog::show() 123 std::string edit_text_contents;
179{ 124 bool is_password = false;
180 // If modal, check to see if we are not displaying alerts, 125
181 // and do any application logic before showing modal alerts 126 setBackgroundVisible(TRUE);
182 if (sDisplayCallback) 127 setBackgroundOpaque(TRUE);
183 {
184 bool show = sDisplayCallback(isModal());
185 if (show == false)
186 {
187 mOptionChosen = mDefaultOption;
188 llinfos << "Alert: " << mLabel << llendl;
189 close();
190 return false;
191 }
192 }
193 128
194 // Check to see if the user wants to ignore this alert 129
195 if (mIgnorable > 0) 130 typedef std::vector<std::pair<std::string, std::string> > options_t;
131 options_t supplied_options;
132
133 // for now, get LLSD to iterator over form elements
134 LLSD form_sd = form->asLLSD();
135
136 S32 option_index = 0;
137 for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it)
196 { 138 {
197 BOOL warn = sSettings->getWarning(mIgnoreLabel); 139 std::string type = (*it)["type"].asString();
198 if (!warn) 140 if (type == "button")
199 { 141 {
200 switch(mIgnorable) 142 if((*it)["default"])
201 { 143 {
202 case IGNORE_USE_DEFAULT: 144 mDefaultOption = option_index;
203 mOptionChosen = mDefaultOption;
204 break;
205 case IGNORE_USE_SAVED:
206 mOptionChosen = sSettings->getS32("Default" + mIgnoreLabel);
207 break;
208 case IGNORE_SHOW_AGAIN:
209 break;
210 } 145 }
211 close();
212 return false;
213 }
214 }
215 146
216 // If this is a caution message, change the color and add an icon. 147 supplied_options.push_back(std::make_pair((*it)["name"].asString(), (*it)["text"].asString()));
217 if (mCaution)
218 {
219 setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertCautionBoxColor" ) );
220 }
221 else
222 {
223 setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertBoxColor" ) );
224 }
225 148
226 // Check to see if we are already displaying the alert 149 ButtonData data;
227 if (mUnique) 150 data.mSelf = this;
228 { 151 if (option_index == mNote->getURLOption())
229 std::map<std::string,LLAlertDialog*>::iterator iter = sUniqueActiveMap.find(mLabel); 152 {
230 if (iter != sUniqueActiveMap.end()) 153 data.mURL = mNote->getURL();
154 }
155
156 mButtonData.push_back(data);
157 option_index++;
158 }
159 else if (type == "text")
231 { 160 {
232 gFloaterView->bringToFront(iter->second); 161 edit_text_contents = (*it)["value"].asString();
233 mUnique = FALSE; // don't remove entry from map on destruction 162 edit_text_name = (*it)["name"].asString();
234 close(); 163 }
235 return false; 164 else if (type == "password")
165 {
166 edit_text_contents = (*it)["value"].asString();
167 edit_text_name = (*it)["name"].asString();
168 is_password = true;
236 } 169 }
237 sUniqueActiveMap[mLabel] = this;
238 }
239 startModal();
240 gFloaterView->adjustToFitScreen(this, FALSE);
241 open(); /* Flawfinder: ignore */
242 setFocus(TRUE);
243 if (mLineEditor)
244 {
245 mLineEditor->setFocus(TRUE);
246 mLineEditor->selectAll();
247 }
248 if(mDefaultOption >= 0)
249 {
250 // delay before enabling default button
251 mDefaultBtnTimer.start();
252 mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
253 } 170 }
254 return true;
255}
256
257void LLAlertDialog::format(std::string& msg, const LLStringUtil::format_map_t& args)
258{
259 // XUI:translate!
260 LLStringUtil::format_map_t targs = args;
261 targs["[SECOND_LIFE]"] = "Second Life";
262 targs["[_URL]"] = mURL;
263 LLStringUtil::format(msg, targs);
264}
265 171
266void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_option,
267 const std::string& msg_in, const LLStringUtil::format_map_t& args,
268 const std::string& edit_text)
269{
270 setBackgroundVisible(TRUE);
271 setBackgroundOpaque(TRUE);
272
273 const LLFontGL* font = LLResMgr::getInstance()->getRes( font_name );
274 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
275 const S32 EDITOR_HEIGHT = 20;
276
277 const options_list_t* optionsp = &options_in;
278
279 // Buttons 172 // Buttons
280 options_list_t default_option_list; 173 options_t options;
281 mNumOptions = options_in.size(); 174 if (supplied_options.empty())
282 if( 0 == mNumOptions )
283 { 175 {
284 default_option_list.push_back("Close"); 176 options.push_back(std::make_pair(std::string("close"), std::string("Close")));
285 optionsp = &default_option_list; 177
286 default_option = 0; 178 // add data for ok button.
287 mNumOptions = 1; 179 ButtonData ok_button;
180 ok_button.mSelf = this;
181
182 mButtonData.push_back(ok_button);
183 mDefaultOption = 0;
184 }
185 else
186 {
187 options = supplied_options;
288 } 188 }
289 189
290 const options_list_t& options= *optionsp; 190 S32 num_options = options.size();
291
292 mButtonData = new ButtonData[mNumOptions];
293 191
294 // Calc total width of buttons 192 // Calc total width of buttons
295 S32 button_width = 0; 193 S32 button_width = 0;
296 S32 sp = font->getWidth(std::string("OO")); 194 S32 sp = font->getWidth(std::string("OO"));
297 for( S32 i = 0; i < mNumOptions; i++ ) 195 for( S32 i = 0; i < num_options; i++ )
298 { 196 {
299 S32 w = S32(font->getWidth( options[i] ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD; 197 S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
300 button_width = llmax( w, button_width ); 198 button_width = llmax( w, button_width );
301 } 199 }
302 S32 btn_total_width = button_width; 200 S32 btn_total_width = button_width;
303 if( mNumOptions > 1 ) 201 if( num_options > 1 )
304 { 202 {
305 btn_total_width = (mNumOptions * button_width) + ((mNumOptions - 1) * BTN_HPAD); 203 btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD);
306 } 204 }
307 205
308 // Message: create text box using raw string, as text has been structure deliberately 206 // Message: create text box using raw string, as text has been structure deliberately
309 // Use size of created text box to generate dialog box size 207 // Use size of created text box to generate dialog box size
310 std::string msg = msg_in; 208 std::string msg = mNote->getMessage();
311 format( msg, args );
312 llwarns << "Alert: " << msg << llendl; 209 llwarns << "Alert: " << msg << llendl;
313 LLTextBox* msg_box = new LLTextBox( std::string("Alert message"), msg, (F32)MAX_ALLOWED_MSG_WIDTH, font ); 210 LLTextBox* msg_box = new LLTextBox( std::string("Alert message"), msg, (F32)MAX_ALLOWED_MSG_WIDTH, font );
314 211
@@ -321,16 +218,19 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o
321 dialog_height += LINE_HEIGHT; // room for title bar 218 dialog_height += LINE_HEIGHT; // room for title bar
322 } 219 }
323 220
324 if (edit_text.size() > 0) 221 // 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
222 if (!edit_text_name.empty())
325 { 223 {
326 dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f)); 224 dialog_height += EDITOR_HEIGHT + VPAD;
327 dialog_height += EDITOR_HEIGHT; 225 dialog_width = llmax(dialog_width, (S32)(font->getWidth( edit_text_contents ) + 0.99f));
328 } 226 }
227
329 if (mCaution) 228 if (mCaution)
330 { 229 {
331 // Make room for the caution icon. 230 // Make room for the caution icon.
332 dialog_width += 32 + HPAD; 231 dialog_width += 32 + HPAD;
333 } 232 }
233
334 reshape( dialog_width, dialog_height, FALSE ); 234 reshape( dialog_width, dialog_height, FALSE );
335 235
336 S32 msg_y = getRect().getHeight() - VPAD; 236 S32 msg_y = getRect().getHeight() - VPAD;
@@ -352,6 +252,7 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o
352 { 252 {
353 msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) ); 253 msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) );
354 } 254 }
255
355 LLRect rect; 256 LLRect rect;
356 rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() ); 257 rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() );
357 msg_box->setRect( rect ); 258 msg_box->setRect( rect );
@@ -360,25 +261,26 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o
360 // Buttons 261 // Buttons
361 S32 button_left = (getRect().getWidth() - btn_total_width) / 2; 262 S32 button_left = (getRect().getWidth() - btn_total_width) / 2;
362 263
363 for( S32 i = 0; i < mNumOptions; i++ ) 264 for( S32 i = 0; i < num_options; i++ )
364 { 265 {
365 LLRect button_rect; 266 LLRect button_rect;
366 button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ); 267 button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT );
367 268
368 LLButton* btn = new LLButton(std::string("btn"), button_rect, 269 LLButton* btn = new LLButton(
369 LLStringUtil::null, LLStringUtil::null, LLStringUtil::null, 270 options[i].first, button_rect,
370 &LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i]), 271 "","", "",
371 font, 272 NULL, NULL,
372 options[i], 273 font,
373 options[i]); 274 options[i].second,
275 options[i].second);
374 276
375 mButtonData[i].mSelf = this;
376 mButtonData[i].mButton = btn; 277 mButtonData[i].mButton = btn;
377 mButtonData[i].mOption = i; 278
279 btn->setClickedCallback(&LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i]));
378 280
379 addChild(btn); 281 addChild(btn);
380 282
381 if( i == default_option ) 283 if( i == mDefaultOption )
382 { 284 {
383 btn->setFocus(TRUE); 285 btn->setFocus(TRUE);
384 } 286 }
@@ -387,21 +289,83 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o
387 } 289 }
388 290
389 // (Optional) Edit Box 291 // (Optional) Edit Box
390 if (edit_text.size() > 0) 292 if (!edit_text_name.empty())
391 { 293 {
392 S32 y = VPAD + BTN_HEIGHT + VPAD/2; 294 S32 y = VPAD + BTN_HEIGHT + VPAD/2;
393 mLineEditor = new LLLineEditor(std::string("lineeditor"), 295 mLineEditor = new LLLineEditor(edit_text_name,
394 LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y), 296 LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y),
395 edit_text, 297 edit_text_contents,
396 LLFontGL::sSansSerif, 298 LLFontGL::getFontSansSerif(),
397 STD_STRING_STR_LEN); 299 STD_STRING_STR_LEN);
300
301 // make sure all edit keys get handled properly (DEV-22396)
302 mLineEditor->setHandleEditKeysDirectly(TRUE);
303
398 addChild(mLineEditor); 304 addChild(mLineEditor);
399 } 305 }
306
307 if (mLineEditor)
308 {
309 mLineEditor->setDrawAsterixes(is_password);
310
311 setEditTextArgs(notification->getSubstitutions());
312 }
313
314 std::string ignore_label;
315
316 if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
317 {
318 setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
319 }
320 else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
321 {
322 setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
323 }
324}
325
326// All logic for deciding not to show an alert is done here,
327// so that the alert is valid until show() is called.
328bool LLAlertDialog::show()
329{
330 // If this is a caution message, change the color and add an icon.
331 if (mCaution)
332 {
333 setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertCautionBoxColor" ) );
334 }
335 else
336 {
337 setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertBoxColor" ) );
338 }
339
340 startModal();
341 gFloaterView->adjustToFitScreen(this, FALSE);
342 open(); /* Flawfinder: ignore */
343 setFocus(TRUE);
344 if (mLineEditor)
345 {
346 mLineEditor->setFocus(TRUE);
347 mLineEditor->selectAll();
348 }
349 if(mDefaultOption >= 0)
350 {
351 // delay before enabling default button
352 mDefaultBtnTimer.start();
353 mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
354 }
355
356 // attach to floater if necessary
357 LLUUID context_key = mNote->getPayload()["context"].asUUID();
358 LLFloaterNotificationContext* contextp = dynamic_cast<LLFloaterNotificationContext*>(LLNotificationContext::getInstance(context_key));
359 if (contextp && contextp->getFloater())
360 {
361 contextp->getFloater()->addDependentFloater(this, FALSE);
362 }
363 return true;
400} 364}
401 365
402bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::string& check_control ) 366bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::string& check_control )
403{ 367{
404 const LLFontGL* font = LLResMgr::getInstance()->getRes( font_name ); 368 const LLFontGL* font = LLResMgr::getInstance()->getRes( FONT_NAME );
405 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); 369 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
406 370
407 // Extend dialog for "check next time" 371 // Extend dialog for "check next time"
@@ -422,16 +386,9 @@ bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::stri
422 check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, 386 check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2,
423 max_msg_width, LINE_HEIGHT); 387 max_msg_width, LINE_HEIGHT);
424 388
425 mCheck = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font); 389 mCheck = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font, onClickIgnore, this);
426 addChild(mCheck); 390 addChild(mCheck);
427 391
428 // mCheck is sometimes "show again" and sometimes "hide" :-(
429 // If it's "Show Again", and we showed it, it must be checked. JC
430 if (mIgnorable == IGNORE_SHOW_AGAIN)
431 {
432 mCheck->setValue(TRUE);
433 }
434
435 return true; 392 return true;
436} 393}
437 394
@@ -449,65 +406,12 @@ void LLAlertDialog::setVisible( BOOL visible )
449void LLAlertDialog::onClose(bool app_quitting) 406void LLAlertDialog::onClose(bool app_quitting)
450{ 407{
451 LLModalDialog::onClose(app_quitting); 408 LLModalDialog::onClose(app_quitting);
452 handleCallbacks();
453} 409}
454 410
455LLAlertDialog::~LLAlertDialog() 411LLAlertDialog::~LLAlertDialog()
456{ 412{
457 delete[] mButtonData;
458 if (mUnique)
459 {
460 sUniqueActiveMap.erase(mLabel);
461 }
462} 413}
463 414
464void LLAlertDialog::handleCallbacks()
465{
466 if (mOptionChosen >= 0)
467 {
468 if (mTextCallback && mLineEditor)
469 {
470 mTextCallback(mOptionChosen, mLineEditor->getText(), mUserData);
471 }
472 else if (mCallback)
473 {
474 mCallback(mOptionChosen, mUserData);
475 }
476
477 // If we declared a URL and chose the URL option, go to the url
478 if (mOptionChosen == mURLOption)
479 {
480 if (!mURL.empty() && sURLLoader != NULL)
481 {
482 sURLLoader->load(mURL);
483 }
484 }
485
486 // Only change warn state if we actually warned.
487 if (mCheck
488 && sSettings->getWarning(mIgnoreLabel))
489 {
490 // mCheck sometimes means "hide and do the default" and
491 // other times means "warn me again". Yuck. JC
492 BOOL check = mCheck->getValue();
493 switch(mIgnorable)
494 {
495 case IGNORE_USE_DEFAULT:
496 sSettings->setWarning(mIgnoreLabel, !check);
497 break;
498 case IGNORE_USE_SAVED:
499 sSettings->setWarning(mIgnoreLabel, !check);
500 sSettings->setS32("Default" + mIgnoreLabel, mOptionChosen);
501 break;
502 case IGNORE_SHOW_AGAIN:
503 sSettings->setWarning(mIgnoreLabel, check);
504 break;
505 default:
506 break;
507 }
508 }
509 }
510}
511BOOL LLAlertDialog::hasTitleBar() const 415BOOL LLAlertDialog::hasTitleBar() const
512{ 416{
513 return (getCurrentTitle() != "" && getCurrentTitle() != " ") // has title 417 return (getCurrentTitle() != "" && getCurrentTitle() != " ") // has title
@@ -567,33 +471,11 @@ void LLAlertDialog::draw()
567 LLModalDialog::draw(); 471 LLModalDialog::draw();
568} 472}
569 473
570void LLAlertDialog::setOptionEnabled( S32 option, BOOL enable ) 474void LLAlertDialog::setEditTextArgs(const LLSD& edit_args)
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 LLStringUtil::format_map_t& edit_args)
592{ 475{
593 if (mLineEditor) 476 if (mLineEditor)
594 { 477 {
595 std::string msg = mLineEditor->getText(); 478 std::string msg = mLineEditor->getText();
596 format(msg, edit_args);
597 mLineEditor->setText(msg); 479 mLineEditor->setText(msg);
598 } 480 }
599 else 481 else
@@ -602,268 +484,44 @@ void LLAlertDialog::setEditTextArgs(const LLStringUtil::format_map_t& edit_args)
602 } 484 }
603} 485}
604 486
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 487// static
618void LLAlertDialog::onButtonPressed( void* userdata ) 488void LLAlertDialog::onButtonPressed( void* userdata )
619{ 489{
620 ButtonData* button_data = (ButtonData*)userdata; 490 ButtonData* button_data = (ButtonData*)userdata;
621 LLAlertDialog* self = button_data->mSelf; 491 LLAlertDialog* self = button_data->mSelf;
622 492
623 self->mOptionChosen = button_data->mOption; 493 LLSD response = self->mNote->getResponseTemplate();
624 self->close(); // deletes self 494 if (self->mLineEditor)
625}
626
627//=============================================================================
628
629//static
630const std::string& LLAlertDialog::getTemplateMessage(const std::string& xml_desc)
631{
632 template_map_t::iterator iter = sAlertTemplates.find(xml_desc);
633 if (iter != sAlertTemplates.end())
634 { 495 {
635 return iter->second->mMessage; 496 response[self->mLineEditor->getName()] = self->mLineEditor->getValue();
636 } 497 }
637 else 498 response[button_data->mButton->getName()] = true;
499
500 // If we declared a URL and chose the URL option, go to the url
501 if (!button_data->mURL.empty() && sURLLoader != NULL)
638 { 502 {
639 return xml_desc; 503 sURLLoader->load(button_data->mURL);
640 } 504 }
505
506 self->mNote->respond(response); // new notification reponse
507 self->close(); // deletes self
641} 508}
642 509
643//static 510//static
644bool LLAlertDialog::parseAlerts(const std::string& xml_filename, LLControlGroup* settings, BOOL settings_only) 511void LLAlertDialog::onClickIgnore(LLUICtrl* ctrl, void* user_data)
645{ 512{
646 LLXMLNodePtr root; 513 LLAlertDialog* self = (LLAlertDialog*)user_data;
647 BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
648 514
649 if (!success || root.isNull() || !root->hasName( "alerts" )) 515 // checkbox sometimes means "hide and do the default" and
516 // other times means "warn me again". Yuck. JC
517 BOOL check = ctrl->getValue();
518 if (self->mNote->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
650 { 519 {
651 llerrs << "Problem reading UI Alerts file: " << xml_filename << llendl; 520 // question was "show again" so invert value to get "ignore"
652 return false; 521 check = !check;
653 } 522 }
654 523
655 BOOL add_settings = FALSE; 524 self->mNote->setIgnored(check);
656 if (settings) 525}
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("global"))
667 {
668 std::string global_name;
669 if (alert->getAttributeString("name", global_name))
670 {
671 if (global_name == "skipnexttime")
672 {
673 sStringSkipNextTime = alert->getTextContents();
674 }
675 else if (global_name == "alwayschoose")
676 {
677 sStringAlwaysChoose = alert->getTextContents();
678 }
679 }
680 continue;
681 }
682
683 if (!alert->hasName("alert"))
684 {
685 continue;
686 }
687
688 LLAlertDialogTemplate* xml_template = settings_only ? NULL : new LLAlertDialogTemplate;
689
690 // name=
691 std::string alert_name;
692 if (alert->getAttributeString("name", alert_name))
693 {
694 if (xml_template)
695 {
696 xml_template->mLabel = alert_name;
697 }
698 }
699 else
700 {
701 llwarns << "Unable to parse alert with no name" << llendl;
702 delete xml_template;
703 continue;
704 }
705 // title=
706 std::string title;
707 if (alert->getAttributeString("title", title))
708 {
709 if (xml_template)
710 {
711 xml_template->mTitle = title;
712 }
713 }
714 // modal=
715 BOOL modal;
716 if (alert->getAttributeBOOL("modal", modal))
717 {
718 if (xml_template)
719 {
720 xml_template->mModal = modal;
721 }
722 }
723 // caution=
724 BOOL caution;
725 if (alert->getAttributeBOOL("caution", caution))
726 {
727 if (xml_template)
728 {
729 xml_template->mCaution = caution;
730 }
731 }
732 // unique=
733 BOOL unique;
734 if (alert->getAttributeBOOL("unique", unique))
735 {
736 if (xml_template)
737 {
738 xml_template->mUnique = unique;
739 }
740 }
741
742 S32 default_option = 0;
743 BOOL nodefault;
744 if (alert->getAttributeBOOL("nodefault", nodefault))
745 {
746 if (nodefault)
747 {
748 if (xml_template)
749 {
750 xml_template->mDefaultOption = -1;
751 }
752 default_option = -1;
753 }
754 }
755
756 S32 btn_idx = 0;
757 for (LLXMLNode* child = alert->getFirstChild();
758 child != NULL; child = child->getNextSibling())
759 {
760 // <message>
761 if (child->hasName("message"))
762 {
763 if (xml_template)
764 {
765 xml_template->mMessage = child->getTextContents();
766 }
767 }
768 526
769 // <option>
770 if (child->hasName("option"))
771 {
772 std::string label = child->getTextContents();
773 BOOL is_default = FALSE;
774 child->getAttributeBOOL("default", is_default);
775 std::string ignore_text;
776 if (!child->getAttributeString("ignore", ignore_text))
777 {
778 ignore_text = label;
779 }
780 if (xml_template)
781 {
782 xml_template->addOption(label, ignore_text, is_default);
783 }
784 if (is_default)
785 {
786 default_option = btn_idx;
787 }
788 btn_idx++;
789 }
790
791 // <editline>
792 if (child->hasName("editline"))
793 {
794 if (xml_template)
795 {
796 xml_template->mEditLineText = child->getTextContents();
797 if (xml_template->mEditLineText.empty())
798 {
799 xml_template->mEditLineText = " ";
800 }
801 }
802 }
803
804 // <ignore>
805 if (child->hasName("ignore"))
806 {
807 std::string ignore_text = child->getTextContents();
808 // label=
809 std::string name;
810 child->getAttributeString("name", name);
811
812 //always set to alert_name for the sake of i18n
813 //if (name.empty())
814 name = alert_name;
815
816 if (xml_template)
817 {
818 xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_DEFAULT;
819 xml_template->mIgnoreListText = ignore_text;
820 xml_template->mIgnoreLabel = name;
821 }
822 if (!ignore_text.empty())
823 {
824 if (add_settings)
825 {
826 settings->addWarning(name);
827 }
828 if (xml_template)
829 {
830 sIgnorableTemplates[name] = xml_template; // will override any previous entry
831 }
832 }
833 // save_option=
834 BOOL save_option = FALSE;
835 child->getAttributeBOOL("save_option", save_option);
836 if (save_option)
837 {
838 if (xml_template)
839 {
840 xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_SAVED;
841 }
842 if (add_settings)
843 {
844 settings->declareS32(std::string("Default") + name, default_option, std::string("Default option number for this alert dialog"));
845 }
846 }
847 }
848 527
849 // <url>
850 if (child->hasName("url"))
851 {
852 S32 url_option = 0;
853 child->getAttributeS32("option", url_option);
854 if (xml_template)
855 {
856 xml_template->mURL = child->getTextContents();
857 xml_template->mURLOption = url_option;
858 }
859 }
860
861 }
862 if (xml_template)
863 {
864 xml_template->mDefaultOption = default_option;
865 sAlertTemplates[xml_template->mLabel] = xml_template;
866 }
867 }
868 return true;
869}