/indra/newview/llscreenchannel.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 972 lines · 707 code · 154 blank · 111 comment · 160 complexity · d4836e02390ed45f8c864c1d703d667a MD5 · raw file

  1. /**
  2. * @file llscreenchannel.cpp
  3. * @brief Class implements a channel on a screen in which appropriate toasts may appear.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h" // must be first include
  27. #include "lliconctrl.h"
  28. #include "lltextbox.h"
  29. #include "llscreenchannel.h"
  30. #include "lltoastpanel.h"
  31. #include "llviewercontrol.h"
  32. #include "llviewerwindow.h"
  33. #include "llfloaterreg.h"
  34. #include "lltrans.h"
  35. #include "lldockablefloater.h"
  36. #include "llsyswellwindow.h"
  37. #include "llimfloater.h"
  38. #include "llscriptfloater.h"
  39. #include "llrootview.h"
  40. #include <algorithm>
  41. using namespace LLNotificationsUI;
  42. bool LLScreenChannel::mWasStartUpToastShown = false;
  43. LLFastTimer::DeclareTimer FTM_GET_CHANNEL_RECT("Calculate Notification Channel Region");
  44. LLRect LLScreenChannelBase::getChannelRect()
  45. {
  46. LLFastTimer _(FTM_GET_CHANNEL_RECT);
  47. if (mFloaterSnapRegion == NULL)
  48. {
  49. mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region");
  50. }
  51. if (mChicletRegion == NULL)
  52. {
  53. mChicletRegion = gViewerWindow->getRootView()->getChildView("chiclet_container");
  54. }
  55. LLRect channel_rect;
  56. LLRect chiclet_rect;
  57. mFloaterSnapRegion->localRectToScreen(mFloaterSnapRegion->getLocalRect(), &channel_rect);
  58. mChicletRegion->localRectToScreen(mChicletRegion->getLocalRect(), &chiclet_rect);
  59. channel_rect.mTop = chiclet_rect.mBottom;
  60. return channel_rect;
  61. }
  62. //--------------------------------------------------------------------------
  63. //////////////////////
  64. // LLScreenChannelBase
  65. //////////////////////
  66. LLScreenChannelBase::LLScreenChannelBase(const Params& p)
  67. : LLUICtrl(p),
  68. mToastAlignment(p.toast_align),
  69. mCanStoreToasts(true),
  70. mHiddenToastsNum(0),
  71. mHoveredToast(NULL),
  72. mControlHovering(false),
  73. mShowToasts(true),
  74. mID(p.id),
  75. mDisplayToastsAlways(p.display_toasts_always),
  76. mChannelAlignment(p.channel_align),
  77. mFloaterSnapRegion(NULL),
  78. mChicletRegion(NULL)
  79. {
  80. mID = p.id;
  81. setMouseOpaque( false );
  82. setVisible(FALSE);
  83. }
  84. BOOL LLScreenChannelBase::postBuild()
  85. {
  86. if (mFloaterSnapRegion == NULL)
  87. {
  88. mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region");
  89. }
  90. if (mChicletRegion == NULL)
  91. {
  92. mChicletRegion = gViewerWindow->getRootView()->getChildView("chiclet_container");
  93. }
  94. return TRUE;
  95. }
  96. void LLScreenChannelBase::reshape(S32 width, S32 height, BOOL called_from_parent)
  97. {
  98. redrawToasts();
  99. }
  100. bool LLScreenChannelBase::isHovering()
  101. {
  102. if (!mHoveredToast)
  103. {
  104. return false;
  105. }
  106. return mHoveredToast->isHovered();
  107. }
  108. void LLScreenChannelBase::updatePositionAndSize(LLRect rect)
  109. {
  110. LLRect this_rect = getRect();
  111. this_rect.mTop = rect.mTop;
  112. switch(mChannelAlignment)
  113. {
  114. case CA_LEFT :
  115. break;
  116. case CA_CENTRE :
  117. this_rect.setCenterAndSize( (rect.getWidth()) / 2, rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight());
  118. break;
  119. case CA_RIGHT :
  120. this_rect.setLeftTopAndSize(rect.mRight - this_rect.getWidth(),
  121. this_rect.mTop,
  122. this_rect.getWidth(),
  123. this_rect.getHeight());
  124. }
  125. setRect(this_rect);
  126. redrawToasts();
  127. }
  128. void LLScreenChannelBase::init(S32 channel_left, S32 channel_right)
  129. {
  130. // top and bottom set by updateRect()
  131. setRect(LLRect(channel_left, 0, channel_right, 0));
  132. updateRect();
  133. setVisible(TRUE);
  134. }
  135. void LLScreenChannelBase::updateRect()
  136. {
  137. S32 channel_top = getChannelRect().mTop;
  138. S32 channel_bottom = getChannelRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
  139. S32 channel_left = getRect().mLeft;
  140. S32 channel_right = getRect().mRight;
  141. setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
  142. }
  143. //--------------------------------------------------------------------------
  144. //////////////////////
  145. // LLScreenChannel
  146. //////////////////////
  147. //--------------------------------------------------------------------------
  148. LLScreenChannel::LLScreenChannel(const Params& p)
  149. : LLScreenChannelBase(p),
  150. mStartUpToastPanel(NULL)
  151. {
  152. }
  153. //--------------------------------------------------------------------------
  154. void LLScreenChannel::init(S32 channel_left, S32 channel_right)
  155. {
  156. LLScreenChannelBase::init(channel_left, channel_right);
  157. LLRect channel_rect = getChannelRect();
  158. updatePositionAndSize(channel_rect);
  159. }
  160. //--------------------------------------------------------------------------
  161. LLScreenChannel::~LLScreenChannel()
  162. {
  163. }
  164. std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)
  165. {
  166. std::list<LLToast*> res;
  167. // collect stored toasts
  168. for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it
  169. != mStoredToastList.end(); it++)
  170. {
  171. if (matcher.matches(it->toast->getNotification()))
  172. {
  173. res.push_back(it->toast);
  174. }
  175. }
  176. // collect displayed toasts
  177. for (std::vector<ToastElem>::iterator it = mToastList.begin(); it
  178. != mToastList.end(); it++)
  179. {
  180. if (matcher.matches(it->toast->getNotification()))
  181. {
  182. res.push_back(it->toast);
  183. }
  184. }
  185. return res;
  186. }
  187. //--------------------------------------------------------------------------
  188. void LLScreenChannel::updatePositionAndSize(LLRect new_world_rect)
  189. {
  190. LLRect this_rect = getRect();
  191. switch(mChannelAlignment)
  192. {
  193. case CA_LEFT :
  194. this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());
  195. break;
  196. case CA_CENTRE :
  197. LLScreenChannelBase::updatePositionAndSize(new_world_rect);
  198. return;
  199. case CA_RIGHT :
  200. this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());
  201. this_rect.setLeftTopAndSize(new_world_rect.mRight - this_rect.getWidth(),
  202. this_rect.mTop,
  203. this_rect.getWidth(),
  204. this_rect.getHeight());
  205. }
  206. setRect(this_rect);
  207. redrawToasts();
  208. }
  209. //--------------------------------------------------------------------------
  210. void LLScreenChannel::addToast(const LLToast::Params& p)
  211. {
  212. bool store_toast = false, show_toast = false;
  213. mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show);
  214. store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;
  215. if(!show_toast && !store_toast)
  216. {
  217. mRejectToastSignal(p.notif_id);
  218. return;
  219. }
  220. ToastElem new_toast_elem(p);
  221. new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1));
  222. new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1));
  223. if(mControlHovering)
  224. {
  225. new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
  226. new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, new_toast_elem.toast));
  227. new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, new_toast_elem.toast));
  228. }
  229. if(show_toast)
  230. {
  231. mToastList.push_back(new_toast_elem);
  232. if(p.can_be_stored)
  233. {
  234. // store toasts immediately - EXT-3762
  235. storeToast(new_toast_elem);
  236. }
  237. updateShowToastsState();
  238. redrawToasts();
  239. }
  240. else // store_toast
  241. {
  242. mHiddenToastsNum++;
  243. storeToast(new_toast_elem);
  244. }
  245. }
  246. //--------------------------------------------------------------------------
  247. void LLScreenChannel::onToastDestroyed(LLToast* toast)
  248. {
  249. std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
  250. if(it != mToastList.end())
  251. {
  252. mToastList.erase(it);
  253. }
  254. it = find(mStoredToastList.begin(), mStoredToastList.end(), static_cast<LLPanel*>(toast));
  255. if(it != mStoredToastList.end())
  256. {
  257. mStoredToastList.erase(it);
  258. }
  259. // if destroyed toast is hovered - reset hovered
  260. if (mHoveredToast == toast)
  261. {
  262. mHoveredToast = NULL;
  263. }
  264. }
  265. //--------------------------------------------------------------------------
  266. void LLScreenChannel::onToastFade(LLToast* toast)
  267. {
  268. std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
  269. if(it != mToastList.end())
  270. {
  271. bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
  272. if(delete_toast)
  273. {
  274. mToastList.erase(it);
  275. deleteToast(toast);
  276. }
  277. else
  278. {
  279. storeToast((*it));
  280. mToastList.erase(it);
  281. }
  282. redrawToasts();
  283. }
  284. }
  285. //--------------------------------------------------------------------------
  286. void LLScreenChannel::deleteToast(LLToast* toast)
  287. {
  288. if (toast->isDead())
  289. {
  290. return;
  291. }
  292. // send signal to observers about destroying of a toast
  293. toast->mOnDeleteToastSignal(toast);
  294. // update channel's Hovering state
  295. // turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard
  296. if(mHoveredToast == toast)
  297. {
  298. mHoveredToast = NULL;
  299. }
  300. // close the toast
  301. toast->closeFloater();
  302. }
  303. //--------------------------------------------------------------------------
  304. void LLScreenChannel::storeToast(ToastElem& toast_elem)
  305. {
  306. // do not store clones
  307. std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.id);
  308. if( it != mStoredToastList.end() )
  309. return;
  310. mStoredToastList.push_back(toast_elem);
  311. mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id);
  312. }
  313. //--------------------------------------------------------------------------
  314. void LLScreenChannel::loadStoredToastsToChannel()
  315. {
  316. std::vector<ToastElem>::iterator it;
  317. if(mStoredToastList.size() == 0)
  318. return;
  319. for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
  320. {
  321. (*it).toast->setIsHidden(false);
  322. (*it).toast->startTimer();
  323. mToastList.push_back((*it));
  324. }
  325. mStoredToastList.clear();
  326. redrawToasts();
  327. }
  328. //--------------------------------------------------------------------------
  329. void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
  330. {
  331. std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
  332. if( it == mStoredToastList.end() )
  333. return;
  334. LLToast* toast = (*it).toast;
  335. if(toast->getVisible())
  336. {
  337. // toast is already in channel
  338. return;
  339. }
  340. toast->setIsHidden(false);
  341. toast->startTimer();
  342. mToastList.push_back((*it));
  343. redrawToasts();
  344. }
  345. //--------------------------------------------------------------------------
  346. void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id)
  347. {
  348. // *TODO: may be remove this function
  349. std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
  350. if( it == mStoredToastList.end() )
  351. return;
  352. LLToast* toast = (*it).toast;
  353. mStoredToastList.erase(it);
  354. mRejectToastSignal(toast->getNotificationID());
  355. }
  356. //--------------------------------------------------------------------------
  357. void LLScreenChannel::killToastByNotificationID(LLUUID id)
  358. {
  359. // searching among toasts on a screen
  360. std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
  361. if( it != mToastList.end())
  362. {
  363. LLToast* toast = (*it).toast;
  364. // if it is a notification toast and notification is UnResponded - then respond on it
  365. // else - simply destroy a toast
  366. //
  367. // NOTE: if a notification is unresponded this function will be called twice for the same toast.
  368. // At first, the notification will be discarded, at second (it will be caused by discarding),
  369. // the toast will be destroyed.
  370. if(toast->isNotificationValid())
  371. {
  372. mRejectToastSignal(toast->getNotificationID());
  373. }
  374. else
  375. {
  376. mToastList.erase(it);
  377. deleteToast(toast);
  378. redrawToasts();
  379. }
  380. return;
  381. }
  382. // searching among stored toasts
  383. it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
  384. if( it != mStoredToastList.end() )
  385. {
  386. LLToast* toast = (*it).toast;
  387. mStoredToastList.erase(it);
  388. // send signal to a listener to let him perform some action on toast rejecting
  389. mRejectToastSignal(toast->getNotificationID());
  390. deleteToast(toast);
  391. }
  392. }
  393. void LLScreenChannel::killMatchedToasts(const Matcher& matcher)
  394. {
  395. std::list<LLToast*> to_delete = findToasts(matcher);
  396. for (std::list<LLToast*>::iterator it = to_delete.begin(); it
  397. != to_delete.end(); it++)
  398. {
  399. killToastByNotificationID((*it)-> getNotificationID());
  400. }
  401. }
  402. //--------------------------------------------------------------------------
  403. void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
  404. {
  405. std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
  406. if( it != mToastList.end() && panel)
  407. {
  408. LLToast* toast = (*it).toast;
  409. LLPanel* old_panel = toast->getPanel();
  410. toast->removeChild(old_panel);
  411. delete old_panel;
  412. toast->insertPanel(panel);
  413. toast->startTimer();
  414. redrawToasts();
  415. }
  416. }
  417. //--------------------------------------------------------------------------
  418. void LLScreenChannel::redrawToasts()
  419. {
  420. if (!getParent())
  421. {
  422. // connect to floater snap region just to get resize events, we don't care about being a proper widget
  423. mFloaterSnapRegion->addChild(this);
  424. setFollows(FOLLOWS_ALL);
  425. }
  426. if(mToastList.size() == 0)
  427. return;
  428. switch(mToastAlignment)
  429. {
  430. case NA_TOP :
  431. showToastsTop();
  432. break;
  433. case NA_CENTRE :
  434. showToastsCentre();
  435. break;
  436. case NA_BOTTOM :
  437. showToastsBottom();
  438. }
  439. }
  440. //--------------------------------------------------------------------------
  441. void LLScreenChannel::showToastsBottom()
  442. {
  443. LLRect toast_rect;
  444. S32 bottom = getRect().mBottom - gFloaterView->getRect().mBottom;
  445. S32 toast_margin = 0;
  446. std::vector<ToastElem>::reverse_iterator it;
  447. updateRect();
  448. LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
  449. for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
  450. {
  451. if(it != mToastList.rbegin())
  452. {
  453. LLToast* toast = (*(it-1)).toast;
  454. bottom = toast->getRect().mTop - toast->getTopPad();
  455. toast_margin = gSavedSettings.getS32("ToastGap");
  456. }
  457. toast_rect = (*it).toast->getRect();
  458. toast_rect.setOriginAndSize(getRect().mRight - toast_rect.getWidth(),
  459. bottom + toast_margin, toast_rect.getWidth(),
  460. toast_rect.getHeight());
  461. (*it).toast->setRect(toast_rect);
  462. if(floater && floater->overlapsScreenChannel())
  463. {
  464. if(it == mToastList.rbegin())
  465. {
  466. // move first toast above docked floater
  467. S32 shift = floater->getRect().getHeight();
  468. if(floater->getDockControl())
  469. {
  470. shift += floater->getDockControl()->getTongueHeight();
  471. }
  472. (*it).toast->translate(0, shift);
  473. }
  474. LLRect channel_rect = getChannelRect();
  475. // don't show toasts if there is not enough space
  476. if(toast_rect.mTop > channel_rect.mTop)
  477. {
  478. break;
  479. }
  480. }
  481. bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;
  482. if(!stop_showing_toasts)
  483. {
  484. if( it != mToastList.rend()-1)
  485. {
  486. S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
  487. stop_showing_toasts = toast_top > getRect().mTop;
  488. }
  489. }
  490. // at least one toast should be visible
  491. if(it == mToastList.rbegin())
  492. {
  493. stop_showing_toasts = false;
  494. }
  495. if(stop_showing_toasts)
  496. break;
  497. if( !(*it).toast->getVisible() )
  498. {
  499. // HACK
  500. // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
  501. (*it).toast->setVisible(TRUE);
  502. }
  503. if(!(*it).toast->hasFocus())
  504. {
  505. // Fixing Z-order of toasts (EXT-4862)
  506. // Next toast will be positioned under this one.
  507. gFloaterView->sendChildToBack((*it).toast);
  508. }
  509. }
  510. // Dismiss toasts we don't have space for (STORM-391).
  511. if(it != mToastList.rend())
  512. {
  513. mHiddenToastsNum = 0;
  514. for(; it != mToastList.rend(); it++)
  515. {
  516. (*it).toast->hide();
  517. }
  518. }
  519. }
  520. //--------------------------------------------------------------------------
  521. void LLScreenChannel::showToastsCentre()
  522. {
  523. LLRect toast_rect;
  524. S32 bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2;
  525. std::vector<ToastElem>::reverse_iterator it;
  526. for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
  527. {
  528. toast_rect = (*it).toast->getRect();
  529. toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight());
  530. (*it).toast->setRect(toast_rect);
  531. (*it).toast->setVisible(TRUE);
  532. }
  533. }
  534. //--------------------------------------------------------------------------
  535. void LLScreenChannel::showToastsTop()
  536. {
  537. LLRect channel_rect = getChannelRect();
  538. LLRect toast_rect;
  539. S32 top = channel_rect.mTop;
  540. S32 toast_margin = 0;
  541. std::vector<ToastElem>::reverse_iterator it;
  542. updateRect();
  543. LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
  544. for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
  545. {
  546. if(it != mToastList.rbegin())
  547. {
  548. LLToast* toast = (*(it-1)).toast;
  549. top = toast->getRect().mBottom - toast->getTopPad();
  550. toast_margin = gSavedSettings.getS32("ToastGap");
  551. }
  552. toast_rect = (*it).toast->getRect();
  553. toast_rect.setLeftTopAndSize(channel_rect.mRight - toast_rect.getWidth(),
  554. top, toast_rect.getWidth(),
  555. toast_rect.getHeight());
  556. (*it).toast->setRect(toast_rect);
  557. if(floater && floater->overlapsScreenChannel())
  558. {
  559. if(it == mToastList.rbegin())
  560. {
  561. // move first toast above docked floater
  562. S32 shift = -floater->getRect().getHeight();
  563. if(floater->getDockControl())
  564. {
  565. shift -= floater->getDockControl()->getTongueHeight();
  566. }
  567. (*it).toast->translate(0, shift);
  568. }
  569. LLRect channel_rect = getChannelRect();
  570. // don't show toasts if there is not enough space
  571. if(toast_rect.mBottom < channel_rect.mBottom)
  572. {
  573. break;
  574. }
  575. }
  576. bool stop_showing_toasts = (*it).toast->getRect().mBottom < channel_rect.mBottom;
  577. if(!stop_showing_toasts)
  578. {
  579. if( it != mToastList.rend()-1)
  580. {
  581. S32 toast_bottom = (*it).toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");
  582. stop_showing_toasts = toast_bottom < channel_rect.mBottom;
  583. }
  584. }
  585. // at least one toast should be visible
  586. if(it == mToastList.rbegin())
  587. {
  588. stop_showing_toasts = false;
  589. }
  590. if(stop_showing_toasts)
  591. break;
  592. if( !(*it).toast->getVisible() )
  593. {
  594. // HACK
  595. // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
  596. (*it).toast->setVisible(TRUE);
  597. }
  598. if(!(*it).toast->hasFocus())
  599. {
  600. // Fixing Z-order of toasts (EXT-4862)
  601. // Next toast will be positioned under this one.
  602. gFloaterView->sendChildToBack((*it).toast);
  603. }
  604. }
  605. // Dismiss toasts we don't have space for (STORM-391).
  606. if(it != mToastList.rend())
  607. {
  608. mHiddenToastsNum = 0;
  609. for(; it != mToastList.rend(); it++)
  610. {
  611. (*it).toast->hide();
  612. }
  613. }
  614. }
  615. //--------------------------------------------------------------------------
  616. void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
  617. {
  618. LLScreenChannelBase::updateRect();
  619. LLRect toast_rect;
  620. LLToast::Params p;
  621. p.lifetime_secs = timer;
  622. p.enable_hide_btn = false;
  623. mStartUpToastPanel = new LLToast(p);
  624. if(!mStartUpToastPanel)
  625. return;
  626. mStartUpToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onStartUpToastHide, this));
  627. LLPanel* wrapper_panel = mStartUpToastPanel->getChild<LLPanel>("wrapper_panel");
  628. LLTextBox* text_box = mStartUpToastPanel->getChild<LLTextBox>("toast_text");
  629. std::string text = LLTrans::getString("StartUpNotifications");
  630. toast_rect = mStartUpToastPanel->getRect();
  631. mStartUpToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true);
  632. text_box->setValue(text);
  633. text_box->setVisible(TRUE);
  634. text_box->reshapeToFitText();
  635. text_box->setOrigin(text_box->getRect().mLeft, (wrapper_panel->getRect().getHeight() - text_box->getRect().getHeight())/2);
  636. toast_rect.setLeftTopAndSize(0, getRect().getHeight() - gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());
  637. mStartUpToastPanel->setRect(toast_rect);
  638. addChild(mStartUpToastPanel);
  639. mStartUpToastPanel->setVisible(TRUE);
  640. }
  641. // static --------------------------------------------------------------------------
  642. F32 LLScreenChannel::getHeightRatio()
  643. {
  644. F32 ratio = gSavedSettings.getF32("NotificationChannelHeightRatio");
  645. if(0.0f > ratio)
  646. {
  647. ratio = 0.0f;
  648. }
  649. else if(1.0f < ratio)
  650. {
  651. ratio = 1.0f;
  652. }
  653. return ratio;
  654. }
  655. //--------------------------------------------------------------------------
  656. void LLScreenChannel::updateStartUpString(S32 num)
  657. {
  658. // *TODO: update string if notifications are arriving while the StartUp toast is on a screen
  659. }
  660. //--------------------------------------------------------------------------
  661. void LLScreenChannel::onStartUpToastHide()
  662. {
  663. onCommit();
  664. }
  665. //--------------------------------------------------------------------------
  666. void LLScreenChannel::closeStartUpToast()
  667. {
  668. if(mStartUpToastPanel != NULL)
  669. {
  670. mStartUpToastPanel->setVisible(FALSE);
  671. mStartUpToastPanel = NULL;
  672. }
  673. }
  674. void LLNotificationsUI::LLScreenChannel::stopToastTimer(LLToast* toast)
  675. {
  676. if (!toast || toast != mHoveredToast) return;
  677. // Pause fade timer of the hovered toast.
  678. toast->stopTimer();
  679. }
  680. void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast)
  681. {
  682. if (!toast || toast == mHoveredToast)
  683. {
  684. return;
  685. }
  686. // Reset its fade timer.
  687. toast->startTimer();
  688. }
  689. //--------------------------------------------------------------------------
  690. void LLScreenChannel::hideToastsFromScreen()
  691. {
  692. for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
  693. (*it).toast->setVisible(FALSE);
  694. }
  695. //--------------------------------------------------------------------------
  696. void LLScreenChannel::hideToast(const LLUUID& notification_id)
  697. {
  698. std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id);
  699. if(mToastList.end() != it)
  700. {
  701. ToastElem te = *it;
  702. te.toast->hide();
  703. }
  704. }
  705. void LLScreenChannel::closeHiddenToasts(const Matcher& matcher)
  706. {
  707. // since we can't guarantee that close toast operation doesn't change mToastList
  708. // we collect matched toasts that should be closed into separate list
  709. std::list<ToastElem> toasts;
  710. for (std::vector<ToastElem>::iterator it = mToastList.begin(); it
  711. != mToastList.end(); it++)
  712. {
  713. LLToast * toast = it->toast;
  714. // add to list valid toast that match to provided matcher criteria
  715. if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL
  716. && !toast->getVisible() && matcher.matches(toast->getNotification()))
  717. {
  718. toasts.push_back(*it);
  719. }
  720. }
  721. // close collected toasts
  722. for (std::list<ToastElem>::iterator it = toasts.begin(); it
  723. != toasts.end(); it++)
  724. {
  725. it->toast->closeFloater();
  726. }
  727. }
  728. //--------------------------------------------------------------------------
  729. void LLScreenChannel::removeToastsFromChannel()
  730. {
  731. hideToastsFromScreen();
  732. for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
  733. {
  734. deleteToast((*it).toast);
  735. }
  736. mToastList.clear();
  737. }
  738. //--------------------------------------------------------------------------
  739. void LLScreenChannel::removeAndStoreAllStorableToasts()
  740. {
  741. if(mToastList.size() == 0)
  742. return;
  743. hideToastsFromScreen();
  744. for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)
  745. {
  746. if((*it).toast->getCanBeStored())
  747. {
  748. storeToast(*(it));
  749. it = mToastList.erase(it);
  750. }
  751. else
  752. {
  753. ++it;
  754. }
  755. }
  756. redrawToasts();
  757. }
  758. //--------------------------------------------------------------------------
  759. void LLScreenChannel::removeToastsBySessionID(LLUUID id)
  760. {
  761. if(mToastList.size() == 0)
  762. return;
  763. hideToastsFromScreen();
  764. for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)
  765. {
  766. if((*it).toast->getSessionID() == id)
  767. {
  768. deleteToast((*it).toast);
  769. it = mToastList.erase(it);
  770. }
  771. else
  772. {
  773. ++it;
  774. }
  775. }
  776. redrawToasts();
  777. }
  778. //--------------------------------------------------------------------------
  779. void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
  780. {
  781. // because of LLViewerWindow::updateUI() that NOT ALWAYS calls onMouseEnter BEFORE onMouseLeave
  782. // we must check hovering directly to prevent incorrect setting for hovering in a channel
  783. if (mouse_enter)
  784. {
  785. if (toast->isHovered())
  786. {
  787. mHoveredToast = toast;
  788. }
  789. }
  790. else if (mHoveredToast != NULL)
  791. {
  792. if (!mHoveredToast->isHovered())
  793. {
  794. mHoveredToast = NULL;
  795. }
  796. }
  797. redrawToasts();
  798. }
  799. //--------------------------------------------------------------------------
  800. void LLScreenChannel::updateShowToastsState()
  801. {
  802. LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
  803. if(!floater)
  804. {
  805. setShowToasts(true);
  806. return;
  807. }
  808. updateRect();
  809. }
  810. //--------------------------------------------------------------------------
  811. LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id)
  812. {
  813. std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(),
  814. mStoredToastList.end(), id);
  815. if (it == mStoredToastList.end())
  816. return NULL;
  817. return it->toast;
  818. }