diff options
Diffstat (limited to 'indra/newview/llscreenchannel.cpp')
-rw-r--r-- | indra/newview/llscreenchannel.cpp | 566 |
1 files changed, 388 insertions, 178 deletions
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 61f4897ed0..d340b304ca 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -41,7 +41,7 @@ #include "llsyswellwindow.h" #include "llimfloater.h" #include "llscriptfloater.h" -#include "llsidetray.h" +#include "llrootview.h" #include <algorithm> @@ -49,76 +49,101 @@ using namespace LLNotificationsUI; bool LLScreenChannel::mWasStartUpToastShown = false; +LLFastTimer::DeclareTimer FTM_GET_CHANNEL_RECT("Calculate Notification Channel Region"); +LLRect LLScreenChannelBase::getChannelRect() +{ + LLFastTimer _(FTM_GET_CHANNEL_RECT); + + if (mFloaterSnapRegion == NULL) + { + mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region"); + } + + if (mChicletRegion == NULL) + { + mChicletRegion = gViewerWindow->getRootView()->getChildView("chiclet_container"); + } + + LLRect channel_rect; + LLRect chiclet_rect; + + mFloaterSnapRegion->localRectToScreen(mFloaterSnapRegion->getLocalRect(), &channel_rect); + mChicletRegion->localRectToScreen(mChicletRegion->getLocalRect(), &chiclet_rect); + + channel_rect.mTop = chiclet_rect.mBottom; + return channel_rect; +} + + //-------------------------------------------------------------------------- ////////////////////// // LLScreenChannelBase ////////////////////// -LLScreenChannelBase::LLScreenChannelBase(const LLUUID& id) : - mToastAlignment(NA_BOTTOM) - ,mCanStoreToasts(true) - ,mHiddenToastsNum(0) - ,mHoveredToast(NULL) - ,mControlHovering(false) - ,mShowToasts(true) -{ - mID = id; - mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannelBase::updatePositionAndSize, this, _1, _2)); +LLScreenChannelBase::LLScreenChannelBase(const Params& p) +: LLUICtrl(p), + mToastAlignment(p.toast_align), + mCanStoreToasts(true), + mHiddenToastsNum(0), + mHoveredToast(NULL), + mControlHovering(false), + mShowToasts(true), + mID(p.id), + mDisplayToastsAlways(p.display_toasts_always), + mChannelAlignment(p.channel_align), + mFloaterSnapRegion(NULL), + mChicletRegion(NULL) +{ + mID = p.id; setMouseOpaque( false ); setVisible(FALSE); } -LLScreenChannelBase::~LLScreenChannelBase() -{ - mWorldViewRectConnection.disconnect(); -} -bool LLScreenChannelBase::isHovering() +BOOL LLScreenChannelBase::postBuild() { - if (!mHoveredToast) + if (mFloaterSnapRegion == NULL) { - return false; + mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region"); } - - return mHoveredToast->isHovered(); + + if (mChicletRegion == NULL) + { + mChicletRegion = gViewerWindow->getRootView()->getChildView("chiclet_container"); + } + + return TRUE; } -bool LLScreenChannelBase::resetPositionAndSize(const LLSD& newvalue) +void LLScreenChannelBase::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLRect rc = gViewerWindow->getWorldViewRectScaled(); - updatePositionAndSize(rc, rc); - return true; + redrawToasts(); } -void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) +bool LLScreenChannelBase::isHovering() { - /* - take sidetray into account - screenchannel should not overlap sidetray - */ - S32 world_rect_padding = 0; - if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE - && LLSideTray::instanceCreated ()) + if (!mHoveredToast) { - LLSideTray* side_bar = LLSideTray::getInstance(); - - if (side_bar->getVisible() && !side_bar->getCollapsed()) - world_rect_padding += side_bar->getRect().getWidth(); + return false; } + return mHoveredToast->isHovered(); +} - S32 top_delta = old_world_rect.mTop - new_world_rect.mTop; +void LLScreenChannelBase::updatePositionAndSize(LLRect rect) +{ LLRect this_rect = getRect(); - this_rect.mTop -= top_delta; + this_rect.mTop = rect.mTop; switch(mChannelAlignment) { case CA_LEFT : break; case CA_CENTRE : - this_rect.setCenterAndSize( (new_world_rect.getWidth() - world_rect_padding) / 2, new_world_rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight()); + this_rect.setCenterAndSize( (rect.getWidth()) / 2, rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight()); break; case CA_RIGHT : - this_rect.setLeftTopAndSize(new_world_rect.mRight - world_rect_padding - this_rect.getWidth(), + this_rect.setLeftTopAndSize(rect.mRight - this_rect.getWidth(), this_rect.mTop, this_rect.getWidth(), this_rect.getHeight()); @@ -130,16 +155,19 @@ void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect ne void LLScreenChannelBase::init(S32 channel_left, S32 channel_right) { - if(LLSideTray::instanceCreated()) - { - LLSideTray* side_bar = LLSideTray::getInstance(); - side_bar->getCollapseSignal().connect(boost::bind(&LLScreenChannelBase::resetPositionAndSize, this, _2)); - } + // top and bottom set by updateRect() + setRect(LLRect(channel_left, 0, channel_right, 0)); + updateRect(); + setVisible(TRUE); +} - S32 channel_top = gViewerWindow->getWorldViewRectScaled().getHeight(); - S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); +void LLScreenChannelBase::updateRect() +{ + S32 channel_top = getChannelRect().mTop; + S32 channel_bottom = getChannelRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); + S32 channel_left = getRect().mLeft; + S32 channel_right = getRect().mRight; setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); - setVisible(TRUE); } //-------------------------------------------------------------------------- @@ -147,18 +175,18 @@ void LLScreenChannelBase::init(S32 channel_left, S32 channel_right) // LLScreenChannel ////////////////////// //-------------------------------------------------------------------------- -LLScreenChannel::LLScreenChannel(LLUUID& id): -LLScreenChannelBase(id) -,mStartUpToastPanel(NULL) -{ +LLScreenChannel::LLScreenChannel(const Params& p) +: LLScreenChannelBase(p), + mStartUpToastPanel(NULL) +{ } //-------------------------------------------------------------------------- void LLScreenChannel::init(S32 channel_left, S32 channel_right) { LLScreenChannelBase::init(channel_left, channel_right); - LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); - updatePositionAndSize(world_rect, world_rect); + LLRect channel_rect = getChannelRect(); + updatePositionAndSize(channel_rect); } //-------------------------------------------------------------------------- @@ -167,17 +195,18 @@ LLScreenChannel::~LLScreenChannel() } -std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) +std::list<const LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) { - std::list<LLToast*> res; + std::list<const LLToast*> res; // collect stored toasts for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it != mStoredToastList.end(); it++) { - if (matcher.matches(it->toast->getNotification())) + const LLToast* toast = it->getToast(); + if (toast && matcher.matches(toast->getNotification())) { - res.push_back(it->toast); + res.push_back(toast); } } @@ -185,9 +214,10 @@ std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) for (std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - if (matcher.matches(it->toast->getNotification())) + const LLToast* toast = it->getToast(); + if (toast && matcher.matches(toast->getNotification())) { - res.push_back(it->toast); + res.push_back(toast); } } @@ -195,22 +225,8 @@ std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) } //-------------------------------------------------------------------------- -void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) +void LLScreenChannel::updatePositionAndSize(LLRect new_world_rect) { - /* - take sidetray into account - screenchannel should not overlap sidetray - */ - S32 world_rect_padding = 0; - if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE - && LLSideTray::instanceCreated ()) - { - LLSideTray* side_bar = LLSideTray::getInstance(); - - if (side_bar->getVisible() && !side_bar->getCollapsed()) - world_rect_padding += side_bar->getRect().getWidth(); - } - - LLRect this_rect = getRect(); switch(mChannelAlignment) @@ -219,11 +235,11 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio()); break; case CA_CENTRE : - LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); + LLScreenChannelBase::updatePositionAndSize(new_world_rect); return; case CA_RIGHT : this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio()); - this_rect.setLeftTopAndSize(new_world_rect.mRight - world_rect_padding - this_rect.getWidth(), + this_rect.setLeftTopAndSize(new_world_rect.mRight - this_rect.getWidth(), this_rect.mTop, this_rect.getWidth(), this_rect.getHeight()); @@ -246,15 +262,16 @@ void LLScreenChannel::addToast(const LLToast::Params& p) return; } - ToastElem new_toast_elem(p); + LLToast* toast = new LLToast(p); + ToastElem new_toast_elem(toast->getHandle()); - new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); - new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); + toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); + toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); if(mControlHovering) { - new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); - new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopFadingToast, this, new_toast_elem.toast)); - new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startFadingToast, this, new_toast_elem.toast)); + toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); + toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, toast)); + toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, toast)); } if(show_toast) @@ -326,13 +343,13 @@ void LLScreenChannel::onToastFade(LLToast* toast) //-------------------------------------------------------------------------- void LLScreenChannel::deleteToast(LLToast* toast) { - if (toast->isDead()) + if (!toast || toast->isDead()) { return; } // send signal to observers about destroying of a toast - toast->mOnDeleteToastSignal(toast); + toast->closeToast(); // update channel's Hovering state // turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard @@ -340,9 +357,6 @@ void LLScreenChannel::deleteToast(LLToast* toast) { mHoveredToast = NULL; } - - // close the toast - toast->closeFloater(); } //-------------------------------------------------------------------------- @@ -350,12 +364,16 @@ void LLScreenChannel::deleteToast(LLToast* toast) void LLScreenChannel::storeToast(ToastElem& toast_elem) { // do not store clones - std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.id); + std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.getID()); if( it != mStoredToastList.end() ) return; - mStoredToastList.push_back(toast_elem); - mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id); + const LLToast* toast = toast_elem.getToast(); + if (toast) + { + mStoredToastList.push_back(toast_elem); + mOnStoreToast(toast->getPanel(), toast->getNotificationID()); + } } //-------------------------------------------------------------------------- @@ -368,9 +386,13 @@ void LLScreenChannel::loadStoredToastsToChannel() for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it) { - (*it).toast->setIsHidden(false); - (*it).toast->startFading(); - mToastList.push_back((*it)); + LLToast* toast = it->getToast(); + if (toast) + { + toast->setIsHidden(false); + toast->startTimer(); + mToastList.push_back(*it); + } } mStoredToastList.clear(); @@ -385,17 +407,19 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) if( it == mStoredToastList.end() ) return; - LLToast* toast = (*it).toast; - - if(toast->getVisible()) + LLToast* toast = it->getToast(); + if (toast) { - // toast is already in channel - return; - } + if(toast->getVisible()) + { + // toast is already in channel + return; + } - toast->setIsHidden(false); - toast->startFading(); - mToastList.push_back((*it)); + toast->setIsHidden(false); + toast->startTimer(); + mToastList.push_back(*it); + } redrawToasts(); } @@ -409,9 +433,19 @@ void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) if( it == mStoredToastList.end() ) return; - LLToast* toast = (*it).toast; - mStoredToastList.erase(it); - mRejectToastSignal(toast->getNotificationID()); + const LLToast* toast = it->getToast(); + if (toast) + { + mRejectToastSignal(toast->getNotificationID()); + } + + // Call find() once more, because the mStoredToastList could have been changed + // in mRejectToastSignal callback and the iterator could have become invalid. + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) + { + mStoredToastList.erase(it); + } } //-------------------------------------------------------------------------- @@ -422,21 +456,22 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) if( it != mToastList.end()) { - LLToast* toast = (*it).toast; + LLToast* toast = it->getToast(); // if it is a notification toast and notification is UnResponded - then respond on it // else - simply destroy a toast // // NOTE: if a notification is unresponded this function will be called twice for the same toast. // At first, the notification will be discarded, at second (it will be caused by discarding), // the toast will be destroyed. - if(toast->isNotificationValid()) + if(toast && toast->isNotificationValid()) { mRejectToastSignal(toast->getNotificationID()); } else { - mToastList.erase(it); + deleteToast(toast); + mToastList.erase(it); redrawToasts(); } return; @@ -445,20 +480,31 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) // searching among stored toasts it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if( it != mStoredToastList.end() ) + if (it != mStoredToastList.end()) + { + LLToast* toast = it->getToast(); + if (toast) + { + // send signal to a listener to let him perform some action on toast rejecting + mRejectToastSignal(toast->getNotificationID()); + deleteToast(toast); + } + } + + // Call find() once more, because the mStoredToastList could have been changed + // in mRejectToastSignal callback and the iterator could have become invalid. + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) { - LLToast* toast = (*it).toast; mStoredToastList.erase(it); - // send signal to a listener to let him perform some action on toast rejecting - mRejectToastSignal(toast->getNotificationID()); - deleteToast(toast); } + } void LLScreenChannel::killMatchedToasts(const Matcher& matcher) { - std::list<LLToast*> to_delete = findToasts(matcher); - for (std::list<LLToast*>::iterator it = to_delete.begin(); it + std::list<const LLToast*> to_delete = findToasts(matcher); + for (std::list<const LLToast*>::iterator it = to_delete.begin(); it != to_delete.end(); it++) { killToastByNotificationID((*it)-> getNotificationID()); @@ -472,12 +518,15 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) if( it != mToastList.end() && panel) { - LLToast* toast = (*it).toast; - LLPanel* old_panel = toast->getPanel(); - toast->removeChild(old_panel); - delete old_panel; - toast->insertPanel(panel); - toast->startFading(); + LLToast* toast = it->getToast(); + if (toast) + { + LLPanel* old_panel = toast->getPanel(); + toast->removeChild(old_panel); + delete old_panel; + toast->insertPanel(panel); + toast->startTimer(); + } redrawToasts(); } } @@ -485,7 +534,14 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) //-------------------------------------------------------------------------- void LLScreenChannel::redrawToasts() { - if(mToastList.size() == 0 || isHovering()) + if (!getParent()) + { + // connect to floater snap region just to get resize events, we don't care about being a proper widget + mFloaterSnapRegion->addChild(this); + setFollows(FOLLOWS_ALL); + } + + if(mToastList.size() == 0) return; switch(mToastAlignment) @@ -511,22 +567,37 @@ void LLScreenChannel::showToastsBottom() S32 toast_margin = 0; std::vector<ToastElem>::reverse_iterator it; + updateRect(); + LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { if(it != mToastList.rbegin()) { - LLToast* toast = (*(it-1)).toast; + LLToast* toast = (it-1)->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + bottom = toast->getRect().mTop - toast->getTopPad(); toast_margin = gSavedSettings.getS32("ToastGap"); } - toast_rect = (*it).toast->getRect(); + LLToast* toast = it->getToast(); + if(!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + toast_rect = toast->getRect(); toast_rect.setOriginAndSize(getRect().mRight - toast_rect.getWidth(), bottom + toast_margin, toast_rect.getWidth(), toast_rect.getHeight()); - (*it).toast->setRect(toast_rect); + toast->setRect(toast_rect); if(floater && floater->overlapsScreenChannel()) { @@ -538,24 +609,24 @@ void LLScreenChannel::showToastsBottom() { shift += floater->getDockControl()->getTongueHeight(); } - (*it).toast->translate(0, shift); + toast->translate(0, shift); } - LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + LLRect channel_rect = getChannelRect(); // don't show toasts if there is not enough space - if(toast_rect.mTop > world_rect.mTop) + if(toast_rect.mTop > channel_rect.mTop) { break; } } - bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop; + bool stop_showing_toasts = toast->getRect().mTop > getRect().mTop; if(!stop_showing_toasts) { if( it != mToastList.rend()-1) { - S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); + S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); stop_showing_toasts = toast_top > getRect().mTop; } } @@ -569,61 +640,191 @@ void LLScreenChannel::showToastsBottom() if(stop_showing_toasts) break; - if( !(*it).toast->getVisible() ) + if( !toast->getVisible() ) { // HACK // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts - (*it).toast->setVisible(TRUE); + toast->setVisible(TRUE); } - if(!(*it).toast->hasFocus()) + if(!toast->hasFocus()) { // Fixing Z-order of toasts (EXT-4862) // Next toast will be positioned under this one. - gFloaterView->sendChildToBack((*it).toast); + gFloaterView->sendChildToBack(toast); } } + // Dismiss toasts we don't have space for (STORM-391). if(it != mToastList.rend()) { mHiddenToastsNum = 0; for(; it != mToastList.rend(); it++) { - (*it).toast->stopFading(); - (*it).toast->setVisible(FALSE); - mHiddenToastsNum++; + LLToast* toast = it->getToast(); + if (toast) + { + toast->hide(); + } } } - else - { - closeOverflowToastPanel(); - } } //-------------------------------------------------------------------------- void LLScreenChannel::showToastsCentre() { - LLRect toast_rect; - S32 bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2; + LLToast* toast = mToastList[0].getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + LLRect toast_rect; + S32 bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2; std::vector<ToastElem>::reverse_iterator it; for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { - toast_rect = (*it).toast->getRect(); + LLToast* toast = it->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + toast_rect = toast->getRect(); toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight()); - (*it).toast->setRect(toast_rect); + toast->setRect(toast_rect); - (*it).toast->setVisible(TRUE); + toast->setVisible(TRUE); } } //-------------------------------------------------------------------------- void LLScreenChannel::showToastsTop() { + LLRect channel_rect = getChannelRect(); + + LLRect toast_rect; + S32 top = channel_rect.mTop; + S32 toast_margin = 0; + std::vector<ToastElem>::reverse_iterator it; + + updateRect(); + + LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); + + for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) + { + if(it != mToastList.rbegin()) + { + LLToast* toast = (it-1)->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + top = toast->getRect().mBottom - toast->getTopPad(); + toast_margin = gSavedSettings.getS32("ToastGap"); + } + + LLToast* toast = it->getToast(); + if (!toast) + { + llwarns << "Attempt to display a deleted toast." << llendl; + return; + } + + toast_rect = toast->getRect(); + toast_rect.setLeftTopAndSize(channel_rect.mRight - toast_rect.getWidth(), + top, toast_rect.getWidth(), + toast_rect.getHeight()); + toast->setRect(toast_rect); + + if(floater && floater->overlapsScreenChannel()) + { + if(it == mToastList.rbegin()) + { + // move first toast above docked floater + S32 shift = -floater->getRect().getHeight(); + if(floater->getDockControl()) + { + shift -= floater->getDockControl()->getTongueHeight(); + } + toast->translate(0, shift); + } + + LLRect channel_rect = getChannelRect(); + // don't show toasts if there is not enough space + if(toast_rect.mBottom < channel_rect.mBottom) + { + break; + } + } + + bool stop_showing_toasts = toast->getRect().mBottom < channel_rect.mBottom; + + if(!stop_showing_toasts) + { + if( it != mToastList.rend()-1) + { + S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap"); + stop_showing_toasts = toast_bottom < channel_rect.mBottom; + } + } + + // at least one toast should be visible + if(it == mToastList.rbegin()) + { + stop_showing_toasts = false; + } + + if(stop_showing_toasts) + break; + + if (!toast->getVisible()) + { + // HACK + // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts + toast->setVisible(TRUE); + } + if (!toast->hasFocus()) + { + // Fixing Z-order of toasts (EXT-4862) + // Next toast will be positioned under this one. + gFloaterView->sendChildToBack(toast); + } + } + + // Dismiss toasts we don't have space for (STORM-391). + std::vector<LLToast*> toasts_to_hide; + if(it != mToastList.rend()) + { + mHiddenToastsNum = 0; + for(; it != mToastList.rend(); it++) + { + LLToast* toast = it->getToast(); + if (toast) + { + toasts_to_hide.push_back(toast); + } + } + } + + for (std::vector<LLToast*>::iterator it = toasts_to_hide.begin(), end_it = toasts_to_hide.end(); + it != end_it; + ++it) + { + (*it)->hide(); + } } //-------------------------------------------------------------------------- void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer) { + LLScreenChannelBase::updateRect(); + LLRect toast_rect; LLToast::Params p; p.lifetime_secs = timer; @@ -646,13 +847,10 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer) text_box->setValue(text); text_box->setVisible(TRUE); - S32 old_height = text_box->getRect().getHeight(); text_box->reshapeToFitText(); text_box->setOrigin(text_box->getRect().mLeft, (wrapper_panel->getRect().getHeight() - text_box->getRect().getHeight())/2); - S32 new_height = text_box->getRect().getHeight(); - S32 height_delta = new_height - old_height; - toast_rect.setLeftTopAndSize(0, toast_rect.getHeight() + height_delta +gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight()); + toast_rect.setLeftTopAndSize(0, getRect().getHeight() - gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight()); mStartUpToastPanel->setRect(toast_rect); addChild(mStartUpToastPanel); @@ -697,15 +895,15 @@ void LLScreenChannel::closeStartUpToast() } } -void LLNotificationsUI::LLScreenChannel::stopFadingToast(LLToast* toast) +void LLNotificationsUI::LLScreenChannel::stopToastTimer(LLToast* toast) { if (!toast || toast != mHoveredToast) return; // Pause fade timer of the hovered toast. - toast->stopFading(); + toast->stopTimer(); } -void LLNotificationsUI::LLScreenChannel::startFadingToast(LLToast* toast) +void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast) { if (!toast || toast == mHoveredToast) { @@ -713,15 +911,24 @@ void LLNotificationsUI::LLScreenChannel::startFadingToast(LLToast* toast) } // Reset its fade timer. - toast->startFading(); + toast->startTimer(); } //-------------------------------------------------------------------------- void LLScreenChannel::hideToastsFromScreen() { - closeOverflowToastPanel(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) - (*it).toast->setVisible(FALSE); + { + LLToast* toast = it->getToast(); + if (toast) + { + toast->setVisible(FALSE); + } + else + { + llwarns << "Attempt to hide a deleted toast." << llendl; + } + } } //-------------------------------------------------------------------------- @@ -730,8 +937,15 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id) std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id); if(mToastList.end() != it) { - ToastElem te = *it; - te.toast->hide(); + LLToast* toast = it->getToast(); + if (toast) + { + toast->hide(); + } + else + { + llwarns << "Attempt to hide a deleted toast." << llendl; + } } } @@ -739,24 +953,25 @@ void LLScreenChannel::closeHiddenToasts(const Matcher& matcher) { // since we can't guarantee that close toast operation doesn't change mToastList // we collect matched toasts that should be closed into separate list - std::list<ToastElem> toasts; + std::list<LLToast*> toasts; for (std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - LLToast * toast = it->toast; + LLToast* toast = it->getToast(); // add to list valid toast that match to provided matcher criteria if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL && !toast->getVisible() && matcher.matches(toast->getNotification())) { - toasts.push_back(*it); + toasts.push_back(toast); } } // close collected toasts - for (std::list<ToastElem>::iterator it = toasts.begin(); it + for (std::list<LLToast*>::iterator it = toasts.begin(); it != toasts.end(); it++) { - it->toast->closeFloater(); + LLToast* toast = *it; + toast->closeFloater(); } } @@ -766,7 +981,7 @@ void LLScreenChannel::removeToastsFromChannel() hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - deleteToast((*it).toast); + deleteToast(it->getToast()); } mToastList.clear(); } @@ -780,9 +995,10 @@ void LLScreenChannel::removeAndStoreAllStorableToasts() hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) { - if((*it).toast->getCanBeStored()) + LLToast* toast = it->getToast(); + if(toast && toast->getCanBeStored()) { - storeToast(*(it)); + storeToast(*it); it = mToastList.erase(it); } else @@ -802,9 +1018,10 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id) hideToastsFromScreen(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();) { - if((*it).toast->getSessionID() == id) + LLToast* toast = it->getToast(); + if(toast && toast->getSessionID() == id) { - deleteToast((*it).toast); + deleteToast(toast); it = mToastList.erase(it); } else @@ -835,8 +1052,7 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter) } } - if(!isHovering()) - redrawToasts(); + redrawToasts(); } //-------------------------------------------------------------------------- @@ -850,13 +1066,7 @@ void LLScreenChannel::updateShowToastsState() return; } - S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; - LLRect this_rect = getRect(); - - if(channel_bottom != this_rect.mBottom) - { - setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom)); - } + updateRect(); } //-------------------------------------------------------------------------- @@ -869,5 +1079,5 @@ LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id) if (it == mStoredToastList.end()) return NULL; - return it->toast; + return it->getToast(); } |