aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llnotify.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/newview/llnotify.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 '')
-rw-r--r--linden/indra/newview/llnotify.cpp745
1 files changed, 745 insertions, 0 deletions
diff --git a/linden/indra/newview/llnotify.cpp b/linden/indra/newview/llnotify.cpp
new file mode 100644
index 0000000..c7d3a95
--- /dev/null
+++ b/linden/indra/newview/llnotify.cpp
@@ -0,0 +1,745 @@
1/**
2 * @file llnotify.cpp
3 * @brief Non-blocking notification that doesn't take keyboard focus.
4 *
5 * Copyright (c) 2003-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 "llviewerprecompiledheaders.h"
29
30#include "llnotify.h"
31
32#include "llchat.h"
33#include "llfocusmgr.h"
34
35#include "llbutton.h"
36#include "llfocusmgr.h"
37#include "llglheaders.h"
38#include "lliconctrl.h"
39#include "lltextbox.h"
40#include "lltexteditor.h"
41#include "lluiconstants.h"
42#include "llui.h"
43#include "llxmlnode.h"
44#include "llalertdialog.h"
45#include "llviewercontrol.h"
46#include "llviewerimagelist.h"
47#include "llfloaterchat.h" // for add_chat_history()
48#include "lloverlaybar.h" // for gOverlayBar
49#include "lluictrlfactory.h"
50
51// Globals
52LLNotifyBoxView* gNotifyBoxView = NULL;
53
54const F32 ANIMATION_TIME = 0.333f;
55
56// statics
57S32 LLNotifyBox::sNotifyBoxCount = 0;
58const LLFontGL* LLNotifyBox::sFont = NULL;
59const LLFontGL* LLNotifyBox::sFontSmall = NULL;
60
61LLNotifyBox::template_map_t LLNotifyBox::sNotifyTemplates;
62
63//---------------------------------------------------------------------------
64// LLNotifyBox
65//---------------------------------------------------------------------------
66
67//static
68void LLNotifyBox::showXml( const LLString& xml_desc, notify_callback_t callback, void *user_data)
69{
70 return showXml(xml_desc, LLString::format_map_t(), callback, user_data);
71}
72
73//static
74void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
75 notify_callback_t callback, void *user_data)
76{
77 LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data);
78 gNotifyBoxView->addChild(notify);
79}
80
81//static
82void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
83 notify_callback_t callback, void *user_data,
84 const option_list_t& options,
85 BOOL layout_script_dialog)
86{
87 LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data, options, layout_script_dialog);
88 gNotifyBoxView->addChild(notify);
89}
90
91//---------------------------------------------------------------------------
92
93LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& args,
94 notify_callback_t callback, void* user_data,
95 const option_list_t& extra_options,
96 BOOL layout_script_dialog)
97 : LLPanel("notify", LLRect(), BORDER_NO),
98 LLEventTimer(gSavedSettings.getF32("NotifyTipDuration")),
99 mIsTip(FALSE),
100 mAnimating(TRUE),
101 mTimer(),
102 mNextBtn(NULL),
103 mCallback(callback),
104 mData(user_data),
105 mNumOptions(0),
106 mDefaultOption(0)
107{
108 // clicking on a button does not steal current focus
109 setIsChrome(TRUE);
110
111 // class init
112 if (!sFont)
113 {
114 sFont = LLFontGL::sSansSerif;
115 sFontSmall = LLFontGL::sSansSerifSmall;
116 }
117
118 // get template
119
120 static LLNotifyBoxTemplate default_template;
121 LLNotifyBoxTemplate* xml_template;
122 template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
123 if (iter != sNotifyTemplates.end())
124 {
125 xml_template = iter->second;
126 }
127 else
128 {
129 LLString tmsg = "[Notification template not found:\n " + xml_desc + " ]";
130 default_template.setMessage(tmsg);
131 xml_template = &default_template;
132 }
133
134 // setup paramaters
135
136 LLString message = xml_template->mMessage;
137 LLAlertDialog::format(message, args);
138
139 option_list_t options = xml_template->mOptions;
140 options.insert(options.end(), extra_options.begin(), extra_options.end());
141
142 // initialize
143
144 mIsTip = xml_template->mIsTip;
145 mIsFocusRoot = !mIsTip;
146 mAnimating = TRUE;
147 mCallback = callback;
148 mData = user_data;
149 mNumOptions = options.size();
150 mDefaultOption = xml_template->mDefaultOption;
151
152 LLRect rect = mIsTip ? getNotifyTipRect(message)
153 : getNotifyRect(mNumOptions, layout_script_dialog);
154 setRect(rect);
155 setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
156 setBackgroundVisible(FALSE);
157 setBackgroundOpaque(TRUE);
158
159 LLIconCtrl* icon;
160 LLTextEditor* text;
161
162 S32 x = HPAD + HPAD;
163 const S32 TOP = mRect.getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
164 const S32 BOTTOM = (S32)sFont->getLineHeight();
165
166 icon = new LLIconCtrl("icon",
167 LLRect(x, TOP, x+32, TOP-32),
168 mIsTip ? "notify_tip_icon.tga" : "notify_box_icon.tga");
169 icon->setMouseOpaque(FALSE);
170 addChild(icon);
171
172 x += HPAD + HPAD + 32;
173
174 const S32 BOTTOM_PAD = VPAD * 3;
175 const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);
176
177 // Tokenization on \n is handled by LLTextBox
178
179 const S32 MAX_LENGTH = 512 + 20 +
180 DB_FIRST_NAME_BUF_SIZE +
181 DB_LAST_NAME_BUF_SIZE +
182 DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title.
183
184 text = new LLTextEditor("box",
185 LLRect(x, TOP, mRect.getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16),
186 MAX_LENGTH,
187 message,
188 sFont,
189 FALSE);
190 text->setWordWrap(TRUE);
191 text->setTakesFocus(FALSE);
192 text->setMouseOpaque(FALSE);
193 text->setBorderVisible(FALSE);
194 text->setTakesNonScrollClicks(FALSE);
195 text->setHideScrollbarForShortDocs(TRUE);
196 text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually
197 // rendered under the text box, therefore we want
198 // the actual text box to be transparent
199 text->setReadOnlyFgColor ( gColors.getColor("NotifyTextColor") );
200 text->setEnabled(FALSE); // makes it read-only
201 text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard)
202 addChild(text);
203
204 if (mIsTip)
205 {
206 // TODO: Make a separate archive for these.
207 LLChat chat(message);
208 chat.mSourceType = CHAT_SOURCE_SYSTEM;
209 gFloaterChat->addChatHistory(chat);
210 }
211 else
212 {
213 LLButton* btn;
214 btn = new LLButton("next",
215 LLRect(mRect.getWidth()-24, BOTTOM_PAD+16, mRect.getWidth()-8, BOTTOM_PAD),
216 "notify_next.tga",
217 "notify_next.tga",
218 "",
219 onClickNext,
220 this,
221 sFont);
222 btn->setToolTip("Next");
223 addChild(btn);
224 mNextBtn = btn;
225
226 S32 btn_width = 90;
227 LLRect btn_rect;
228
229 for (S32 i = 0; i < mNumOptions; i++)
230 {
231 S32 index = i;
232 S32 btn_height= BTN_HEIGHT;
233 const LLFontGL* font = sFont;
234 S32 ignore_pad = 0;
235
236 if (layout_script_dialog)
237 {
238 // Add two "blank" option spaces, before the "Ignore" button
239 index = i + 2;
240 if (i == 0)
241 {
242 // Ignore button is smaller, less wide
243 btn_height = BTN_HEIGHT_SMALL;
244 font = sFontSmall;
245 ignore_pad = 10;
246 }
247 }
248
249 btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad,
250 BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD),
251 btn_width - 2*ignore_pad,
252 btn_height);
253
254 InstanceAndS32* userdata = new InstanceAndS32;
255 userdata->mSelf = this;
256 userdata->mButton = i;
257
258 mBtnCallbackData.put(userdata);
259
260 btn = new LLButton(options[i], btn_rect, "", onClickButton, userdata);
261 btn->setFont(font);
262 addChild(btn, -1);
263
264 if (i == mDefaultOption)
265 {
266 setDefaultBtn(btn);
267 }
268 }
269
270 sNotifyBoxCount++;
271
272 // If this is the only notify box, don't show the next button
273 if (sNotifyBoxCount == 1
274 && mNextBtn)
275 {
276 mNextBtn->setVisible(FALSE);
277 }
278 }
279}
280
281// virtual
282LLNotifyBox::~LLNotifyBox()
283{
284 if (!mIsTip)
285 {
286 sNotifyBoxCount--;
287 }
288 S32 count = mBtnCallbackData.count();
289 for (S32 i = 0; i < count; i++)
290 {
291 delete mBtnCallbackData[i];
292 }
293}
294
295// virtual
296BOOL LLNotifyBox::handleMouseUp(S32 x, S32 y, MASK mask)
297{
298 if (mIsTip)
299 {
300 close();
301 return TRUE;
302 }
303
304 setFocus(TRUE);
305
306 return LLPanel::handleMouseUp(x, y, mask);
307}
308
309// virtual
310BOOL LLNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
311{
312 if (!mIsTip && getVisible() && getEnabled() && pointInView(x,y))
313 {
314 moveToBack();
315 return TRUE;
316 }
317
318 return LLPanel::handleRightMouseDown(x, y, mask);
319}
320
321
322// virtual
323void LLNotifyBox::draw()
324{
325 F32 display_time = mTimer.getElapsedTimeF32();
326
327 if (mAnimating && display_time < ANIMATION_TIME)
328 {
329 glMatrixMode(GL_MODELVIEW);
330 LLUI::pushMatrix();
331
332 S32 height = mRect.getHeight();
333 F32 fraction = display_time / ANIMATION_TIME;
334 F32 voffset = (1.f - fraction) * height;
335 if (mIsTip) voffset *= -1.f;
336 LLUI::translate(0.f, voffset, 0.f);
337
338 drawBackground();
339
340 LLPanel::draw();
341
342 LLUI::popMatrix();
343 }
344 else
345 {
346 if(mAnimating)
347 {
348 mAnimating = FALSE;
349 if(!mIsTip)
350 {
351 // hide everyone behind me once I'm done animating
352 gNotifyBoxView->showOnly(this);
353 }
354 }
355 drawBackground();
356 LLPanel::draw();
357 }
358}
359
360void LLNotifyBox::drawBackground() const
361{
362 LLUUID image_id;
363 image_id.set(gViewerArt.getString("rounded_square.tga"));
364 LLViewerImage* imagep = gImageList.getImage(image_id, MIPMAP_FALSE, TRUE);
365 if (imagep)
366 {
367 LLGLSTexture texture_enabled;
368 LLViewerImage::bindTexture(imagep);
369 LLColor4 color = gColors.getColor("NotifyBoxColor");
370 if(gFocusMgr.childHasKeyboardFocus( this ))
371 {
372 const S32 focus_width = 2;
373 color = gColors.getColor("FloaterFocusBorderColor");
374 glColor4fv(color.mV);
375 gl_segmented_rect_2d_tex(-focus_width, mRect.getHeight() + focus_width,
376 mRect.getWidth() + focus_width, -focus_width,
377 imagep->getWidth(), imagep->getHeight(),
378 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
379 color = gColors.getColor("ColorDropShadow");
380 glColor4fv(color.mV);
381 gl_segmented_rect_2d_tex(0, mRect.getHeight(), mRect.getWidth(), 0, imagep->getWidth(), imagep->getHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
382 color = gColors.getColor("NotifyBoxColor");
383 glColor4fv(color.mV);
384 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);
385 }
386 else
387 {
388 glColor4fv(color.mV);
389 gl_segmented_rect_2d_tex(0, mRect.getHeight(), mRect.getWidth(), 0, imagep->getWidth(), imagep->getHeight(), 16, mIsTip ? ROUNDED_RECT_TOP : ROUNDED_RECT_BOTTOM);
390 }
391 }
392}
393
394
395void LLNotifyBox::close()
396{
397 BOOL isTipTmp = mIsTip;
398 // delete this so that the sNotifyBoxCount is updated properly, so that the
399 // new frontman properly has a next button or not
400 delete this;
401 if(!isTipTmp)
402 {
403 LLNotifyBox * front = gNotifyBoxView->getFirstNontipBox();
404 if(front)
405 {
406 gNotifyBoxView->showOnly(front);
407 // we're assuming that close is only called by user action (for non-tips),
408 // so we then give focus to the next close button
409 front->mDefaultBtn->setFocus(TRUE);
410 gFocusMgr.triggerFocusFlash(); // TODO it's ugly to call this here
411 }
412 }
413}
414
415/*virtual*/
416void LLNotifyBox::tick()
417{
418 if (mIsTip)
419 {
420 close();
421 }
422}
423
424void LLNotifyBox::setVisible(BOOL visible)
425{
426 // properly set the status of the next button
427 if(visible && !mIsTip)
428 {
429 mNextBtn->setVisible(sNotifyBoxCount > 1);
430 mNextBtn->setEnabled(sNotifyBoxCount > 1);
431 }
432 LLPanel::setVisible(visible);
433}
434
435void LLNotifyBox::moveToBack()
436{
437 // Move this dialog to the back.
438 gNotifyBoxView->sendChildToBack(this);
439 if(!mIsTip && mNextBtn)
440 {
441 mNextBtn->setVisible(FALSE);
442
443 // And enable the next button on the frontmost one, if there is one
444 if (gNotifyBoxView->getChildCount() > 0)
445 {
446 LLNotifyBox* front = gNotifyBoxView->getFirstNontipBox();
447 gNotifyBoxView->showOnly(front);
448 // assuming that moveToBack is only called by clicking the next button,
449 // we give focus to the next next button
450 front->mNextBtn->setFocus(TRUE);
451 gFocusMgr.triggerFocusFlash(); // TODO: it's ugly to call this here
452 }
453 }
454}
455
456
457// static
458LLRect LLNotifyBox::getNotifyRect(S32 num_options, BOOL layout_script_dialog)
459{
460 S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight");
461 const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
462
463 const S32 TOP = gNotifyBoxView->getRect().getHeight();
464 const S32 RIGHT = gNotifyBoxView->getRect().getWidth();
465 const S32 LEFT = RIGHT - NOTIFY_WIDTH;
466
467 if (num_options < 1)
468 {
469 num_options = 1;
470 }
471
472 // Add two "blank" option spaces.
473 if (layout_script_dialog)
474 {
475 num_options += 2;
476 }
477
478 S32 additional_lines = (num_options-1) / 3;
479
480 notify_height += additional_lines * (BTN_HEIGHT + VPAD);
481
482 return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
483}
484
485// static
486LLRect LLNotifyBox::getNotifyTipRect(const LLString &utf8message)
487{
488 S32 line_count = 1;
489 LLWString message = utf8str_to_wstring(utf8message);
490 S32 message_len = message.length();
491
492 const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
493 // Make room for the icon area.
494 const S32 text_area_width = NOTIFY_WIDTH - HPAD * 4 - 32;
495
496 const llwchar* wchars = message.c_str();
497 const llwchar* start = wchars;
498 const llwchar* end;
499 S32 total_drawn = 0;
500 BOOL done = FALSE;
501
502 do
503 {
504 line_count++;
505
506 for (end=start; *end != 0 && *end != '\n'; end++)
507 ;
508
509 if( *end == 0 )
510 {
511 end = wchars + message_len;
512 done = TRUE;
513 }
514
515 S32 remaining = end - start;
516 while( remaining )
517 {
518 S32 drawn = sFont->maxDrawableChars( start, (F32)text_area_width, remaining, TRUE );
519
520 if( 0 == drawn )
521 {
522 drawn = 1; // Draw at least one character, even if it doesn't all fit. (avoids an infinite loop)
523 }
524
525 total_drawn += drawn;
526 start += drawn;
527 remaining -= drawn;
528
529 if( total_drawn < message_len )
530 {
531 if( (wchars[ total_drawn ] != '\n') )
532 {
533 // wrap because line was too long
534 line_count++;
535 }
536 }
537 else
538 {
539 done = TRUE;
540 }
541 }
542
543 total_drawn++; // for '\n'
544 end++;
545 start = end;
546 } while( !done );
547
548 const S32 MIN_NOTIFY_HEIGHT = 72;
549 const S32 MAX_NOTIFY_HEIGHT = 600;
550 S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight());
551 if(gOverlayBar)
552 {
553 notify_height += gOverlayBar->getRect().getHeight();
554 }
555 else
556 {
557 // *FIX: this is derived from the padding caused by the
558 // rounded rects, shouldn't be a const here.
559 notify_height += 10;
560 }
561 notify_height += VPAD;
562 notify_height = llclamp(notify_height, MIN_NOTIFY_HEIGHT, MAX_NOTIFY_HEIGHT);
563
564 const S32 RIGHT = gNotifyBoxView->getRect().getWidth();
565 const S32 LEFT = RIGHT - NOTIFY_WIDTH;
566
567 // Make sure it goes slightly offscreen
568 return LLRect(LEFT, notify_height-1, RIGHT, -1);
569}
570
571
572// static
573void LLNotifyBox::onClickButton(void* data)
574{
575 InstanceAndS32* self_and_button = (InstanceAndS32*)data;
576 LLNotifyBox* self = self_and_button->mSelf;
577 S32 button = self_and_button->mButton;
578
579 if (self->mCallback)
580 {
581 self->mCallback(button, self->mData);
582 }
583
584 self->close();
585}
586
587
588// static
589void LLNotifyBox::onClickNext(void* data)
590{
591 LLNotifyBox* self = static_cast<LLNotifyBox*>(data);
592 self->moveToBack();
593}
594
595//-----------------------------------------------------------------------------
596
597//static
598const LLString& LLNotifyBox::getTemplateMessage(const LLString& xml_desc)
599{
600 template_map_t::iterator iter = sNotifyTemplates.find(xml_desc);
601 if (iter != sNotifyTemplates.end())
602 {
603 return iter->second->mMessage;
604 }
605 else
606 {
607 return xml_desc;
608 }
609}
610
611//static
612bool LLNotifyBox::parseNotify(const LLString& xml_filename)
613{
614 LLXMLNodePtr root;
615
616 BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
617
618 if (!success || root.isNull() || !root->hasName( "notifications" ))
619 {
620 llerrs << "Problem reading UI Notify file: " << xml_filename << llendl;
621 return false;
622 }
623
624 for (LLXMLNode* notify = root->getFirstChild();
625 notify != NULL; notify = notify->getNextSibling())
626 {
627 if (!notify->hasName("notify"))
628 {
629 continue;
630 }
631
632 LLNotifyBoxTemplate* xml_template = new LLNotifyBoxTemplate;
633
634 // label=
635 LLString notify_name;
636 if (notify->getAttributeString("name", notify_name))
637 {
638 if (xml_template)
639 {
640 xml_template->mLabel = notify_name;
641 }
642 }
643 else
644 {
645 llwarns << "Unable to parse notify with no name" << llendl;
646 delete xml_template;
647 continue;
648 }
649 // modal=
650 BOOL tip;
651 if (notify->getAttributeBOOL("tip", tip))
652 {
653 if (xml_template)
654 {
655 xml_template->mIsTip = tip;
656 }
657 }
658
659 S32 btn_idx = 0;
660 for (LLXMLNode* child = notify->getFirstChild();
661 child != NULL; child = child->getNextSibling())
662 {
663 // <message>
664 if (child->hasName("message"))
665 {
666 if (xml_template)
667 {
668 xml_template->mMessage = child->getTextContents();
669 }
670 }
671
672 // <option>
673 if (child->hasName("option"))
674 {
675 LLString label = child->getValue();
676 BOOL is_default = FALSE;
677 child->getAttributeBOOL("default", is_default);
678 LLString ignore_text;
679 if (!child->getAttributeString("ignore", ignore_text))
680 {
681 ignore_text = label;
682 }
683 if (xml_template)
684 {
685 xml_template->addOption(label, is_default);
686 }
687 btn_idx++;
688 }
689 }
690
691 //XUI:translate
692 if (xml_template->mOptions.empty())
693 {
694 xml_template->addOption("OK", FALSE);
695 }
696 if (xml_template)
697 {
698 sNotifyTemplates[xml_template->mLabel] = xml_template;
699 }
700 }
701 return true;
702}
703
704LLNotifyBoxView::LLNotifyBoxView(const LLString& name, const LLRect& rect, BOOL mouse_opaque, U32 follows)
705 : LLUICtrl(name,rect,mouse_opaque,NULL,NULL,follows)
706{
707}
708
709LLNotifyBox * LLNotifyBoxView::getFirstNontipBox() const
710{
711 // assumes every child is a notify box
712 for(child_list_const_iter_t iter = getChildList()->begin();
713 iter != getChildList()->end();
714 iter++)
715 {
716 LLNotifyBox * box = static_cast<LLNotifyBox*>(*iter);
717 if(!box->isTip())
718 {
719 return box;
720 }
721 }
722 return NULL;
723}
724
725void LLNotifyBoxView::showOnly(LLView * view)
726{
727 if(view)
728 {
729 // assumes that the argument is actually a child
730 LLNotifyBox * shown = static_cast<LLNotifyBox*>(view);
731 // make every other notification invisible
732 for(child_list_const_iter_t iter = getChildList()->begin();
733 iter != getChildList()->end();
734 iter++)
735 {
736 LLNotifyBox * box = static_cast<LLNotifyBox*>(*iter);
737 if(box != view && box->getVisible() && !box->isTip())
738 {
739 box->setVisible(FALSE);
740 }
741 }
742 shown->setVisible(TRUE);
743 sendChildToFront(shown);
744 }
745}