diff options
Diffstat (limited to 'linden/indra/newview/llnotify.cpp')
-rw-r--r-- | linden/indra/newview/llnotify.cpp | 573 |
1 files changed, 182 insertions, 391 deletions
diff --git a/linden/indra/newview/llnotify.cpp b/linden/indra/newview/llnotify.cpp index bd752af..a436d2d 100644 --- a/linden/indra/newview/llnotify.cpp +++ b/linden/indra/newview/llnotify.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * 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 | 18 | * 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 | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -55,6 +56,8 @@ | |||
55 | #include "lluictrlfactory.h" | 56 | #include "lluictrlfactory.h" |
56 | #include "llversionviewer.h" | 57 | #include "llversionviewer.h" |
57 | 58 | ||
59 | #include "hippoGridManager.h" | ||
60 | |||
58 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0e) | Added: RLVa-0.2.0b | 61 | // [RLVa:KB] - Version: 1.22.11 | Checked: 2009-07-10 (RLVa-1.0.0e) | Added: RLVa-0.2.0b |
59 | #include "rlvhandler.h" | 62 | #include "rlvhandler.h" |
60 | // [/RLVa:KB] | 63 | // [/RLVa:KB] |
@@ -63,133 +66,83 @@ | |||
63 | LLNotifyBoxView* gNotifyBoxView = NULL; | 66 | LLNotifyBoxView* gNotifyBoxView = NULL; |
64 | 67 | ||
65 | const F32 ANIMATION_TIME = 0.333f; | 68 | const F32 ANIMATION_TIME = 0.333f; |
69 | const S32 BOTTOM_PAD = VPAD * 3; | ||
70 | |||
66 | 71 | ||
67 | // statics | 72 | // statics |
68 | S32 LLNotifyBox::sNotifyBoxCount = 0; | 73 | S32 LLNotifyBox::sNotifyBoxCount = 0; |
69 | const LLFontGL* LLNotifyBox::sFont = NULL; | 74 | const LLFontGL* LLNotifyBox::sFont = NULL; |
70 | const LLFontGL* LLNotifyBox::sFontSmall = NULL; | 75 | const LLFontGL* LLNotifyBox::sFontSmall = NULL; |
71 | std::map<std::string, LLNotifyBox*> LLNotifyBox::sOpenUniqueNotifyBoxes; | 76 | std::map<std::string, LLNotifyBox*> LLNotifyBox::sOpenUniqueNotifyBoxes; |
72 | LLPointer<LLNotifyBoxTemplate> LLNotifyBox::sDefaultTemplate; | ||
73 | |||
74 | 77 | ||
75 | LLNotifyBox::template_map_t LLNotifyBox::sNotifyTemplates; | ||
76 | |||
77 | LLNotifyBox::LLNotifyBehavior::LLNotifyBehavior(notify_callback_t callback, void* data) : | ||
78 | mCallback(callback), | ||
79 | mData(data) | ||
80 | { | ||
81 | } | ||
82 | 78 | ||
83 | //--------------------------------------------------------------------------- | 79 | //--------------------------------------------------------------------------- |
84 | // LLNotifyBox | 80 | // LLNotifyBox |
85 | //--------------------------------------------------------------------------- | 81 | //--------------------------------------------------------------------------- |
86 | 82 | ||
87 | //static | 83 | //static |
88 | LLNotifyBox* LLNotifyBox::showXml( const std::string& xml_desc, notify_callback_t callback, void *user_data) | 84 | void LLNotifyBox::initClass() |
89 | { | 85 | { |
90 | return showXml(xml_desc, LLStringUtil::format_map_t(), callback, user_data); | 86 | LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify")); |
91 | } | 87 | LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip")); |
92 | |||
93 | 88 | ||
94 | //static | 89 | LLNotifications::instance().getChannel("Notifications")->connectChanged(&LLNotifyBox::onNotification); |
95 | LLNotifyBox* LLNotifyBox::showXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, BOOL is_caution, | 90 | LLNotifications::instance().getChannel("NotificationTips")->connectChanged(&LLNotifyBox::onNotification); |
96 | notify_callback_t callback, void *user_data) | ||
97 | { | ||
98 | // for script permission prompts | ||
99 | LLPointer<LLNotifyBoxTemplate> xml_template = getTemplate(xml_desc); | ||
100 | LLNotifyBox* notify = findExistingNotify(xml_template, args); | ||
101 | if (notify) | ||
102 | { | ||
103 | delete notify->mBehavior; | ||
104 | notify->mBehavior = new LLNotifyBehavior(callback, user_data); | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | notify = new LLNotifyBox(xml_template, args, callback, user_data, is_caution); | ||
109 | gNotifyBoxView->addChildAtEnd(notify); | ||
110 | notify->moveToBack(); | ||
111 | } | ||
112 | return notify; | ||
113 | } | 91 | } |
114 | 92 | ||
115 | //static | 93 | //static |
116 | LLNotifyBox* LLNotifyBox::showXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, | 94 | bool LLNotifyBox::onNotification(const LLSD& notify) |
117 | notify_callback_t callback, void *user_data) | ||
118 | { | 95 | { |
119 | LLPointer<LLNotifyBoxTemplate> xml_template = getTemplate(xml_desc); | 96 | LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); |
120 | LLNotifyBox* notify = findExistingNotify(xml_template, args); | 97 | |
121 | if (notify) | 98 | if (!notification) return false; |
122 | { | ||
123 | delete notify->mBehavior; | ||
124 | notify->mBehavior = new LLNotifyBehavior(callback, user_data); | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | notify = new LLNotifyBox(xml_template, args, callback, user_data); | ||
129 | gNotifyBoxView->addChildAtEnd(notify); | ||
130 | notify->moveToBack(); | ||
131 | } | ||
132 | return notify; | ||
133 | } | ||
134 | 99 | ||
135 | //static | 100 | if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") |
136 | LLNotifyBox* LLNotifyBox::showXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, | ||
137 | notify_callback_t callback, void *user_data, | ||
138 | const option_list_t& options, | ||
139 | BOOL layout_script_dialog) | ||
140 | { | ||
141 | LLPointer<LLNotifyBoxTemplate> xml_template = getTemplate(xml_desc); | ||
142 | LLNotifyBox* notify = findExistingNotify(xml_template, args); | ||
143 | if (notify) | ||
144 | { | 101 | { |
145 | delete notify->mBehavior; | 102 | //bring existing notification to top |
146 | notify->mBehavior = new LLNotifyBehavior(callback, user_data); | 103 | LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); |
147 | } | 104 | if (boxp && !boxp->isDead()) |
148 | else | 105 | { |
149 | { | 106 | gNotifyBoxView->showOnly(boxp); |
150 | notify = new LLNotifyBox(xml_template, args, callback, user_data, FALSE, options, layout_script_dialog); | 107 | } |
151 | gNotifyBoxView->addChild(notify); | 108 | else |
152 | } | 109 | { |
153 | return notify; | 110 | bool is_script_dialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); |
154 | } | 111 | LLNotifyBox* notify_box = new LLNotifyBox( |
112 | notification, | ||
113 | is_script_dialog); //layout_script_dialog); | ||
155 | 114 | ||
156 | //static | 115 | gNotifyBoxView->addChild(notify_box); |
157 | LLNotifyBox* LLNotifyBox::findExistingNotify(LLPointer<LLNotifyBoxTemplate> notify_template, const LLStringUtil::format_map_t &args) | 116 | } |
158 | { | 117 | } |
159 | if(notify_template->mUnique) | 118 | else if (notify["sigtype"].asString() == "delete") |
160 | { | 119 | { |
161 | std::string message = notify_template->mMessage; | 120 | LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); |
162 | format(message, args); | 121 | if (boxp && !boxp->isDead()) |
163 | unique_map_t::iterator found_it = sOpenUniqueNotifyBoxes.find(notify_template->mLabel + message); | ||
164 | if (found_it != sOpenUniqueNotifyBoxes.end()) | ||
165 | { | 122 | { |
166 | return found_it->second; | 123 | boxp->close(); |
167 | } | 124 | } |
168 | } | 125 | } |
169 | return NULL; | ||
170 | } | ||
171 | 126 | ||
172 | //static | 127 | return false; |
173 | void LLNotifyBox::cleanup() | ||
174 | { | ||
175 | sDefaultTemplate = NULL; | ||
176 | } | 128 | } |
177 | 129 | ||
178 | //--------------------------------------------------------------------------- | 130 | //--------------------------------------------------------------------------- |
179 | 131 | LLNotifyBox::LLNotifyBox(LLNotificationPtr notification, | |
180 | LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLStringUtil::format_map_t& args, | ||
181 | notify_callback_t callback, void* user_data, BOOL is_caution, | ||
182 | const option_list_t& extra_options, | ||
183 | BOOL layout_script_dialog) | 132 | BOOL layout_script_dialog) |
184 | : LLPanel(xml_template->mLabel, LLRect(), BORDER_NO), | 133 | : LLPanel(notification->getName(), LLRect(), BORDER_NO), |
185 | LLEventTimer(xml_template->mDuration), | 134 | LLEventTimer(notification->getExpiration() == LLDate() |
186 | mIsTip(FALSE), | 135 | ? LLDate(LLDate::now().secondsSinceEpoch() + (F64)gSavedSettings.getF32("NotifyTipDuration")) |
136 | : notification->getExpiration()), | ||
137 | LLInstanceTracker<LLNotifyBox, LLUUID>(notification->getID()), | ||
138 | mNotification(notification), | ||
139 | mIsTip(notification->getType() == "notifytip"), | ||
187 | mAnimating(TRUE), | 140 | mAnimating(TRUE), |
188 | mUnique(xml_template->mUnique), | ||
189 | mNextBtn(NULL), | 141 | mNextBtn(NULL), |
190 | mBehavior(new LLNotifyBehavior(callback, user_data)), | ||
191 | mNumOptions(0), | 142 | mNumOptions(0), |
192 | mDefaultOption(0) | 143 | mNumButtons(0), |
144 | mAddedDefaultBtn(FALSE), | ||
145 | mLayoutScriptDialog(layout_script_dialog) | ||
193 | { | 146 | { |
194 | // clicking on a button does not steal current focus | 147 | // clicking on a button does not steal current focus |
195 | setIsChrome(TRUE); | 148 | setIsChrome(TRUE); |
@@ -197,45 +150,33 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt | |||
197 | // class init | 150 | // class init |
198 | if (!sFont) | 151 | if (!sFont) |
199 | { | 152 | { |
200 | sFont = LLFontGL::sSansSerif; | 153 | sFont = LLFontGL::getFontSansSerif(); |
201 | sFontSmall = LLFontGL::sSansSerifSmall; | 154 | sFontSmall = LLFontGL::getFontSansSerifSmall(); |
202 | } | 155 | } |
203 | 156 | ||
204 | // setup paramaters | 157 | // setup paramaters |
205 | 158 | mMessage = notification->getMessage(); | |
206 | mMessage = xml_template->mMessage; | ||
207 | format(mMessage, args); | ||
208 | |||
209 | // use name + formatted text as unique key | ||
210 | if (mUnique) | ||
211 | { | ||
212 | sOpenUniqueNotifyBoxes[xml_template->mLabel + mMessage] = this; | ||
213 | } | ||
214 | |||
215 | option_list_t options = xml_template->mOptions; | ||
216 | options.insert(options.end(), extra_options.begin(), extra_options.end()); | ||
217 | 159 | ||
218 | // initialize | 160 | // initialize |
219 | |||
220 | mIsTip = xml_template->mIsTip; | ||
221 | setFocusRoot(!mIsTip); | 161 | setFocusRoot(!mIsTip); |
222 | 162 | ||
223 | // caution flag can be set explicitly by specifying it in the | 163 | // caution flag can be set explicitly by specifying it in the |
224 | // call to the c'tor, or it can be set implicitly if the | 164 | // notification payload, or it can be set implicitly if the |
225 | // notify xml template specifies that it is a caution | 165 | // notify xml template specifies that it is a caution |
226 | // | 166 | // |
227 | // tip-style notification handle 'caution' differently - | 167 | // tip-style notification handle 'caution' differently - |
228 | // they display the tip in a different color | 168 | // they display the tip in a different color |
229 | mIsCaution = (xml_template->mIsCaution || is_caution); | 169 | mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; |
230 | 170 | ||
231 | // Don't animate if behind other windows | 171 | // Only animate first window |
232 | if( gNotifyBoxView->getChildCount() > 0 ) | 172 | if( gNotifyBoxView->getChildCount() > 0 ) |
233 | mAnimating = FALSE; | 173 | mAnimating = FALSE; |
234 | else | 174 | else |
235 | mAnimating = TRUE; | 175 | mAnimating = TRUE; |
236 | 176 | ||
237 | mNumOptions = options.size(); | 177 | LLNotificationFormPtr form(notification->getForm()); |
238 | mDefaultOption = xml_template->mDefaultOption; | 178 | |
179 | mNumOptions = form->getNumElements(); | ||
239 | 180 | ||
240 | LLRect rect = mIsTip ? getNotifyTipRect(mMessage) | 181 | LLRect rect = mIsTip ? getNotifyTipRect(mMessage) |
241 | : getNotifyRect(mNumOptions, layout_script_dialog, mIsCaution); | 182 | : getNotifyRect(mNumOptions, layout_script_dialog, mIsCaution); |
@@ -289,7 +230,7 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt | |||
289 | caution_box->setColor(gColors.getColor("NotifyCautionWarnColor")); | 230 | caution_box->setColor(gColors.getColor("NotifyCautionWarnColor")); |
290 | caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); | 231 | caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); |
291 | caution_box->setBorderVisible(FALSE); | 232 | caution_box->setBorderVisible(FALSE); |
292 | caution_box->setWrappedText(LLNotifyBox::getTemplateMessage("ScriptQuestionCautionWarn")); | 233 | caution_box->setWrappedText(notification->getMessage()); |
293 | 234 | ||
294 | addChild(caution_box); | 235 | addChild(caution_box); |
295 | 236 | ||
@@ -297,36 +238,38 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt | |||
297 | // it appears below the caution textbox | 238 | // it appears below the caution textbox |
298 | y = y - caution_height; | 239 | y = y - caution_height; |
299 | } | 240 | } |
241 | else | ||
242 | { | ||
300 | 243 | ||
301 | const S32 BOTTOM_PAD = VPAD * 3; | 244 | const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); |
302 | const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); | 245 | |
303 | 246 | // Tokenization on \n is handled by LLTextBox | |
304 | // Tokenization on \n is handled by LLTextBox | 247 | |
305 | 248 | const S32 MAX_LENGTH = 512 + 20 + | |
306 | const S32 MAX_LENGTH = 512 + 20 + | 249 | DB_FIRST_NAME_BUF_SIZE + |
307 | DB_FIRST_NAME_BUF_SIZE + | 250 | DB_LAST_NAME_BUF_SIZE + |
308 | DB_LAST_NAME_BUF_SIZE + | 251 | DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. |
309 | DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. | 252 | |
310 | 253 | text = new LLTextEditor(std::string("box"), | |
311 | text = new LLTextEditor(std::string("box"), | 254 | LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), |
312 | LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), | 255 | MAX_LENGTH, |
313 | MAX_LENGTH, | 256 | mMessage, |
314 | mMessage, | 257 | sFont, |
315 | sFont, | 258 | FALSE); |
316 | FALSE); | 259 | text->setWordWrap(TRUE); |
317 | text->setWordWrap(TRUE); | 260 | text->setTabStop(FALSE); |
318 | text->setTabStop(FALSE); | 261 | text->setMouseOpaque(FALSE); |
319 | text->setMouseOpaque(FALSE); | 262 | text->setBorderVisible(FALSE); |
320 | text->setBorderVisible(FALSE); | 263 | text->setTakesNonScrollClicks(FALSE); |
321 | text->setTakesNonScrollClicks(FALSE); | 264 | text->setHideScrollbarForShortDocs(TRUE); |
322 | text->setHideScrollbarForShortDocs(TRUE); | 265 | text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually |
323 | text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually | 266 | // rendered under the text box, therefore we want |
324 | // rendered under the text box, therefore we want | 267 | // the actual text box to be transparent |
325 | // the actual text box to be transparent | 268 | text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") ); |
326 | text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") ); | 269 | text->setEnabled(FALSE); // makes it read-only |
327 | text->setEnabled(FALSE); // makes it read-only | 270 | text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) |
328 | text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) | 271 | addChild(text); |
329 | addChild(text); | 272 | } |
330 | 273 | ||
331 | if (mIsTip) | 274 | if (mIsTip) |
332 | { | 275 | { |
@@ -358,61 +301,31 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt | |||
358 | addChild(btn); | 301 | addChild(btn); |
359 | mNextBtn = btn; | 302 | mNextBtn = btn; |
360 | 303 | ||
361 | // make caution notification buttons slightly narrower | ||
362 | // so that 3 of them can fit without overlapping the "next" button | ||
363 | S32 btn_width = mIsCaution? 84 : 90; | ||
364 | LLRect btn_rect; | ||
365 | |||
366 | for (S32 i = 0; i < mNumOptions; i++) | 304 | for (S32 i = 0; i < mNumOptions; i++) |
367 | { | 305 | { |
368 | S32 index = i; | ||
369 | S32 btn_height= BTN_HEIGHT; | ||
370 | const LLFontGL* font = sFont; | ||
371 | S32 ignore_pad = 0; | ||
372 | |||
373 | if (layout_script_dialog) | ||
374 | { | ||
375 | // Add two "blank" option spaces, before the "Ignore" button | ||
376 | index = i + 2; | ||
377 | if (i == 0) | ||
378 | { | ||
379 | // Ignore button is smaller, less wide | ||
380 | btn_height = BTN_HEIGHT_SMALL; | ||
381 | font = sFontSmall; | ||
382 | ignore_pad = 10; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad, | ||
387 | BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD), | ||
388 | btn_width - 2*ignore_pad, | ||
389 | btn_height); | ||
390 | 306 | ||
391 | InstanceAndS32* userdata = new InstanceAndS32; | 307 | LLSD form_element = form->getElement(i); |
392 | userdata->mSelf = this; | 308 | if (form_element["type"].asString() != "button") |
393 | userdata->mButton = i; | ||
394 | |||
395 | mBtnCallbackData.push_back(userdata); | ||
396 | |||
397 | btn = new LLButton(options[i], btn_rect, LLStringUtil::null, onClickButton, userdata); | ||
398 | btn->setFont(font); | ||
399 | |||
400 | if (mIsCaution) | ||
401 | { | 309 | { |
402 | btn->setImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); | 310 | continue; |
403 | btn->setDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); | ||
404 | } | 311 | } |
405 | 312 | ||
406 | addChild(btn, -1); | 313 | addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean()); |
314 | } | ||
407 | 315 | ||
408 | if (i == mDefaultOption) | 316 | if (mNumButtons == 0) |
409 | { | 317 | { |
410 | setDefaultBtn(btn); | 318 | addButton("OK", "OK", FALSE, TRUE); |
411 | } | 319 | mAddedDefaultBtn = TRUE; |
412 | } | 320 | } |
413 | 321 | ||
414 | sNotifyBoxCount++; | 322 | sNotifyBoxCount++; |
415 | 323 | ||
324 | if (sNotifyBoxCount <= 0) | ||
325 | { | ||
326 | llwarns << "A notification was mishandled. sNotifyBoxCount = " << sNotifyBoxCount << llendl; | ||
327 | } | ||
328 | |||
416 | // If this is the only notify box, don't show the next button | 329 | // If this is the only notify box, don't show the next button |
417 | if (sNotifyBoxCount == 1 | 330 | if (sNotifyBoxCount == 1 |
418 | && mNextBtn) | 331 | && mNextBtn) |
@@ -425,27 +338,77 @@ LLNotifyBox::LLNotifyBox(LLPointer<LLNotifyBoxTemplate> xml_template, const LLSt | |||
425 | // virtual | 338 | // virtual |
426 | LLNotifyBox::~LLNotifyBox() | 339 | LLNotifyBox::~LLNotifyBox() |
427 | { | 340 | { |
428 | delete mBehavior; | ||
429 | mBehavior = NULL; | ||
430 | |||
431 | std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); | 341 | std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); |
342 | } | ||
343 | |||
344 | // virtual | ||
345 | LLButton* LLNotifyBox::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default) | ||
346 | { | ||
347 | // make caution notification buttons slightly narrower | ||
348 | // so that 3 of them can fit without overlapping the "next" button | ||
349 | S32 btn_width = mIsCaution? 84 : 90; | ||
350 | |||
351 | LLRect btn_rect; | ||
352 | LLButton* btn; | ||
353 | S32 btn_height= BTN_HEIGHT; | ||
354 | const LLFontGL* font = sFont; | ||
355 | S32 ignore_pad = 0; | ||
356 | S32 button_index = mNumButtons; | ||
357 | S32 index = button_index; | ||
358 | S32 x = (HPAD * 4) + 32; | ||
359 | |||
360 | if (mLayoutScriptDialog) | ||
361 | { | ||
362 | // Add two "blank" option spaces, before the "Ignore" button | ||
363 | index = button_index + 2; | ||
364 | if (button_index == 0) | ||
365 | { | ||
366 | // Ignore button is smaller, less wide | ||
367 | btn_height = BTN_HEIGHT_SMALL; | ||
368 | font = sFontSmall; | ||
369 | ignore_pad = 10; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad, | ||
374 | BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD), | ||
375 | btn_width - 2*ignore_pad, | ||
376 | btn_height); | ||
377 | |||
378 | InstanceAndS32* userdata = new InstanceAndS32; | ||
379 | userdata->mSelf = this; | ||
380 | userdata->mButtonName = is_option ? name : ""; | ||
381 | |||
382 | mBtnCallbackData.push_back(userdata); | ||
383 | |||
432 | 384 | ||
433 | if (mUnique) | 385 | btn = new LLButton(name, btn_rect, "", onClickButton, userdata); |
386 | btn->setLabel(label); | ||
387 | btn->setFont(font); | ||
388 | |||
389 | if (mIsCaution) | ||
390 | { | ||
391 | btn->setImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); | ||
392 | btn->setDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor")); | ||
393 | } | ||
394 | |||
395 | addChild(btn, -1); | ||
396 | |||
397 | if (is_default) | ||
434 | { | 398 | { |
435 | sOpenUniqueNotifyBoxes.erase(getName() + mMessage); | 399 | setDefaultBtn(btn); |
436 | } | 400 | } |
401 | |||
402 | mNumButtons++; | ||
403 | return btn; | ||
437 | } | 404 | } |
438 | 405 | ||
439 | // virtual | ||
440 | BOOL LLNotifyBox::handleMouseUp(S32 x, S32 y, MASK mask) | 406 | BOOL LLNotifyBox::handleMouseUp(S32 x, S32 y, MASK mask) |
441 | { | 407 | { |
442 | if (mIsTip) | 408 | if (mIsTip) |
443 | { | 409 | { |
444 | if (mBehavior->mCallback) | 410 | mNotification->respond(mNotification->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON)); |
445 | { | 411 | |
446 | mBehavior->mCallback(0, mBehavior->mData); | ||
447 | mBehavior->mCallback = NULL; // Notification callbacks only expect to be called once ever | ||
448 | } | ||
449 | close(); | 412 | close(); |
450 | return TRUE; | 413 | return TRUE; |
451 | } | 414 | } |
@@ -583,10 +546,18 @@ void LLNotifyBox::close() | |||
583 | 546 | ||
584 | void LLNotifyBox::format(std::string& msg, const LLStringUtil::format_map_t& args) | 547 | void LLNotifyBox::format(std::string& msg, const LLStringUtil::format_map_t& args) |
585 | { | 548 | { |
586 | // XUI:translate! | ||
587 | LLStringUtil::format_map_t targs = args; | 549 | LLStringUtil::format_map_t targs = args; |
588 | targs["[SECOND_LIFE]"] = "Second Life"; | 550 | |
589 | targs["[VIEWER]"] = IMP_VIEWER_NAME; | 551 | // These sort of things are actually set in llui/llnotifications.cpp |
552 | // so that they will affect all notifications, not just boxes. | ||
553 | |||
554 | // targs["[SECOND_LIFE]"] = LLNotifications::instance().getGlobalString("SECOND_LIFE"); | ||
555 | // targs["[VIEWER_NAME]"] = LLNotifications::instance().getGlobalString("VIEWER_NAME"); | ||
556 | |||
557 | //targs["[GRID_NAME]"] = gHippoGridManager->getConnectedGrid()->getGridName(); | ||
558 | //targs["[GRID_SITE]"] = gHippoGridManager->getConnectedGrid()->getWebSite(); | ||
559 | //targs["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); | ||
560 | |||
590 | LLStringUtil::format(msg, targs); | 561 | LLStringUtil::format(msg, targs); |
591 | } | 562 | } |
592 | 563 | ||
@@ -771,26 +742,14 @@ void LLNotifyBox::onClickButton(void* data) | |||
771 | { | 742 | { |
772 | InstanceAndS32* self_and_button = (InstanceAndS32*)data; | 743 | InstanceAndS32* self_and_button = (InstanceAndS32*)data; |
773 | LLNotifyBox* self = self_and_button->mSelf; | 744 | LLNotifyBox* self = self_and_button->mSelf; |
774 | S32 button = self_and_button->mButton; | 745 | std::string button_name = self_and_button->mButtonName; |
775 | 746 | ||
776 | // for caution notifications, check if the last button in the prompt was clicked | 747 | LLSD response = self->mNotification->getResponseTemplate(); |
777 | // unless it is the only button, in which case it will just be an "OK" button | 748 | if (!self->mAddedDefaultBtn && !button_name.empty()) |
778 | if ((self->mIsCaution) && (button > 0) && (button == (self->mNumOptions - 1))) | ||
779 | { | 749 | { |
780 | // show an alert dialog containing more explanation about the debit permission | 750 | response[button_name] = true; |
781 | LLAlertDialog::showXml("DebitPermissionDetails"); | ||
782 | |||
783 | // keep this notification open | ||
784 | return; | ||
785 | } | 751 | } |
786 | 752 | self->mNotification->respond(response); | |
787 | if (self->mBehavior->mCallback) | ||
788 | { | ||
789 | self->mBehavior->mCallback(button, self->mBehavior->mData); | ||
790 | self->mBehavior->mCallback = NULL; // Notification callbacks only expect to be called once ever | ||
791 | } | ||
792 | |||
793 | self->close(); | ||
794 | } | 753 | } |
795 | 754 | ||
796 | 755 | ||
@@ -801,174 +760,6 @@ void LLNotifyBox::onClickNext(void* data) | |||
801 | self->moveToBack(true); | 760 | self->moveToBack(true); |
802 | } | 761 | } |
803 | 762 | ||
804 | // static | ||
805 | LLPointer<LLNotifyBoxTemplate> LLNotifyBox::getTemplate(const std::string& xml_desc) | ||
806 | { | ||
807 | // get template | ||
808 | |||
809 | if (!sDefaultTemplate) | ||
810 | { | ||
811 | // default template is non-unique, of course | ||
812 | sDefaultTemplate = new LLNotifyBoxTemplate(FALSE, gSavedSettings.getF32("NotifyTipDuration")); | ||
813 | sDefaultTemplate->addOption("OK", FALSE); | ||
814 | } | ||
815 | |||
816 | LLPointer<LLNotifyBoxTemplate> xml_template; | ||
817 | template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); | ||
818 | if (iter != sNotifyTemplates.end()) | ||
819 | { | ||
820 | xml_template = iter->second; | ||
821 | } | ||
822 | else | ||
823 | { | ||
824 | std::string tmsg = "[Notification template not found:\n " + xml_desc + " ]"; | ||
825 | sDefaultTemplate->setMessage(tmsg); | ||
826 | xml_template = sDefaultTemplate; | ||
827 | } | ||
828 | |||
829 | return xml_template; | ||
830 | } | ||
831 | |||
832 | //----------------------------------------------------------------------------- | ||
833 | |||
834 | //static | ||
835 | const std::string LLNotifyBox::getTemplateMessage(const std::string& xml_desc, const LLStringUtil::format_map_t& args) | ||
836 | { | ||
837 | template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); | ||
838 | if (iter != sNotifyTemplates.end()) | ||
839 | { | ||
840 | std::string message = iter->second->mMessage; | ||
841 | format(message, args); | ||
842 | return message; | ||
843 | } | ||
844 | else | ||
845 | { | ||
846 | return xml_desc; | ||
847 | } | ||
848 | } | ||
849 | |||
850 | //static | ||
851 | const std::string LLNotifyBox::getTemplateMessage(const std::string& xml_desc) | ||
852 | { | ||
853 | template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); | ||
854 | if (iter != sNotifyTemplates.end()) | ||
855 | { | ||
856 | return iter->second->mMessage; | ||
857 | } | ||
858 | else | ||
859 | { | ||
860 | return xml_desc; | ||
861 | } | ||
862 | } | ||
863 | |||
864 | // method to check whether a given notify template show as a caution or not | ||
865 | BOOL LLNotifyBox::getTemplateIsCaution(const std::string& xml_desc) | ||
866 | { | ||
867 | BOOL is_caution = FALSE; | ||
868 | |||
869 | template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); | ||
870 | if (iter != sNotifyTemplates.end()) | ||
871 | { | ||
872 | is_caution = iter->second->mIsCaution; | ||
873 | } | ||
874 | |||
875 | return is_caution; | ||
876 | } | ||
877 | |||
878 | //static | ||
879 | bool LLNotifyBox::parseNotify(const std::string& xml_filename) | ||
880 | { | ||
881 | LLXMLNodePtr root; | ||
882 | |||
883 | BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); | ||
884 | |||
885 | if (!success || root.isNull() || !root->hasName( "notifications" )) | ||
886 | { | ||
887 | llerrs << "Problem reading UI Notify file: " << xml_filename << llendl; | ||
888 | return false; | ||
889 | } | ||
890 | |||
891 | for (LLXMLNode* notify = root->getFirstChild(); | ||
892 | notify != NULL; notify = notify->getNextSibling()) | ||
893 | { | ||
894 | if (!notify->hasName("notify")) | ||
895 | { | ||
896 | continue; | ||
897 | } | ||
898 | |||
899 | BOOL unique = FALSE; | ||
900 | notify->getAttributeBOOL("unique", unique); | ||
901 | |||
902 | F32 duration = gSavedSettings.getF32("NotifyTipDuration"); | ||
903 | notify->getAttributeF32("duration", duration); | ||
904 | |||
905 | LLPointer<LLNotifyBoxTemplate> xml_template = new LLNotifyBoxTemplate(unique, duration); | ||
906 | |||
907 | // label= | ||
908 | std::string notify_name; | ||
909 | if (notify->getAttributeString("name", notify_name)) | ||
910 | { | ||
911 | xml_template->mLabel = notify_name; | ||
912 | } | ||
913 | else | ||
914 | { | ||
915 | llwarns << "Unable to parse notify with no name" << llendl; | ||
916 | continue; | ||
917 | } | ||
918 | // modal= | ||
919 | BOOL tip; | ||
920 | if (notify->getAttributeBOOL("tip", tip)) | ||
921 | { | ||
922 | xml_template->mIsTip = tip; | ||
923 | } | ||
924 | |||
925 | // parse a bool attribute named "caution" to determine | ||
926 | // whether this notification gets cautionary special handling | ||
927 | BOOL caution = FALSE; | ||
928 | if (notify->getAttributeBOOL("caution", caution)) | ||
929 | { | ||
930 | if (xml_template) | ||
931 | { | ||
932 | xml_template->mIsCaution = caution; | ||
933 | } | ||
934 | } | ||
935 | |||
936 | |||
937 | S32 btn_idx = 0; | ||
938 | for (LLXMLNode* child = notify->getFirstChild(); | ||
939 | child != NULL; child = child->getNextSibling()) | ||
940 | { | ||
941 | // <message> | ||
942 | if (child->hasName("message")) | ||
943 | { | ||
944 | xml_template->mMessage = child->getTextContents(); | ||
945 | } | ||
946 | |||
947 | // <option> | ||
948 | if (child->hasName("option")) | ||
949 | { | ||
950 | std::string label = child->getValue(); | ||
951 | BOOL is_default = FALSE; | ||
952 | child->getAttributeBOOL("default", is_default); | ||
953 | std::string ignore_text; | ||
954 | if (!child->getAttributeString("ignore", ignore_text)) | ||
955 | { | ||
956 | ignore_text = label; | ||
957 | } | ||
958 | xml_template->addOption(label, is_default); | ||
959 | btn_idx++; | ||
960 | } | ||
961 | } | ||
962 | |||
963 | //*TODO:translate | ||
964 | if (xml_template->mOptions.empty()) | ||
965 | { | ||
966 | xml_template->addOption("OK", FALSE); | ||
967 | } | ||
968 | sNotifyTemplates[xml_template->mLabel] = xml_template; | ||
969 | } | ||
970 | return true; | ||
971 | } | ||
972 | 763 | ||
973 | LLNotifyBoxView::LLNotifyBoxView(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows) | 764 | LLNotifyBoxView::LLNotifyBoxView(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows) |
974 | : LLUICtrl(name,rect,mouse_opaque,NULL,NULL,follows) | 765 | : LLUICtrl(name,rect,mouse_opaque,NULL,NULL,follows) |
@@ -1045,7 +836,7 @@ void LLNotifyBoxView::purgeMessagesMatching(const Matcher& matcher) | |||
1045 | } | 836 | } |
1046 | 837 | ||
1047 | LLNotifyBox* notification = (LLNotifyBox*)*iter; | 838 | LLNotifyBox* notification = (LLNotifyBox*)*iter; |
1048 | if(matcher.matches(notification->getNotifyCallback(), notification->getUserData())) | 839 | if(matcher.matches(notification->getNotification())) |
1049 | { | 840 | { |
1050 | removeChild(notification); | 841 | removeChild(notification); |
1051 | } | 842 | } |