diff options
Diffstat (limited to 'indra/newview/lltoast.cpp')
| -rw-r--r-- | indra/newview/lltoast.cpp | 1266 |
1 files changed, 633 insertions, 633 deletions
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index f6fadf276c..b99514e742 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -1,633 +1,633 @@ -/** - * @file lltoast.cpp - * @brief This class implements a placeholder for any notification panel. - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" // must be first include - -#include "lltoast.h" - -#include "llbutton.h" -#include "llfocusmgr.h" -#include "llnotifications.h" -#include "llviewercontrol.h" - -using namespace LLNotificationsUI; -std::list<LLToast*> LLToast::sModalToastsList; - -//-------------------------------------------------------------------------- -LLToastLifeTimer::LLToastLifeTimer(LLToast* toast, F32 period) - : mToast(toast), - LLEventTimer(period) -{ -} - -/*virtual*/ -bool LLToastLifeTimer::tick() -{ - if (mEventTimer.hasExpired()) - { - mToast->expire(); - } - return false; -} - -void LLToastLifeTimer::stop() -{ - mEventTimer.stop(); -} - -void LLToastLifeTimer::start() -{ - mEventTimer.start(); -} - -void LLToastLifeTimer::restart() -{ - mEventTimer.reset(); -} - -bool LLToastLifeTimer::getStarted() -{ - return mEventTimer.getStarted(); -} - -void LLToastLifeTimer::setPeriod(F32 period) -{ - mPeriod = period; -} - -F32 LLToastLifeTimer::getRemainingTimeF32() -{ - F32 et = mEventTimer.getElapsedTimeF32(); - if (!getStarted() || et > mPeriod) return 0.0f; - return mPeriod - et; -} - -//-------------------------------------------------------------------------- -LLToast::Params::Params() -: can_fade("can_fade", true), - can_be_stored("can_be_stored", true), - is_modal("is_modal", false), - is_tip("is_tip", false), - enable_hide_btn("enable_hide_btn", true), - force_show("force_show", false), - force_store("force_store", false), - fading_time_secs("fading_time_secs", gSavedSettings.getS32("ToastFadingTime")), - lifetime_secs("lifetime_secs", gSavedSettings.getS32("NotificationToastLifeTime")) -{}; - -LLToast::LLToast(const LLToast::Params& p) -: LLModalDialog(LLSD(), p.is_modal), - mToastLifetime(p.lifetime_secs), - mToastFadingTime(p.fading_time_secs), - mNotificationID(p.notif_id), - mSessionID(p.session_id), - mCanFade(p.can_fade), - mCanBeStored(p.can_be_stored), - mHideBtnEnabled(p.enable_hide_btn), - mHideBtn(NULL), - mPanel(NULL), - mNotification(p.notification), - mIsHidden(false), - mHideBtnPressed(false), - mIsTip(p.is_tip), - mWrapperPanel(NULL), - mIsFading(false), - mIsHovered(false) -{ - mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs)); - - buildFromFile("panel_toast.xml"); - - setCanDrag(false); - - mWrapperPanel = getChild<LLPanel>("wrapper_panel"); - - setBackgroundOpaque(true); // *TODO: obsolete - updateTransparency(); - - if(p.panel()) - { - insertPanel(p.panel); - } - - if(mHideBtnEnabled) - { - mHideBtn = getChild<LLButton>("hide_btn"); - mHideBtn->setClickedCallback(boost::bind(&LLToast::hide,this)); - } - - // init callbacks if present - if(!p.on_delete_toast().empty()) - { - mOnDeleteToastSignal.connect(p.on_delete_toast()); - } - - if (isModal()) - { - sModalToastsList.push_front(this); - } -} - -void LLToast::reshape(S32 width, S32 height, bool called_from_parent) -{ - // We shouldn't use reshape from LLModalDialog since it changes toasts position. - // Toasts position should be controlled only by toast screen channel, see LLScreenChannelBase. - // see EXT-8044 - LLFloater::reshape(width, height, called_from_parent); -} - -//-------------------------------------------------------------------------- -bool LLToast::postBuild() -{ - if(!mCanFade) - { - mTimer->stop(); - } - - return true; -} - -//-------------------------------------------------------------------------- -void LLToast::setHideButtonEnabled(bool enabled) -{ - if(mHideBtn) - mHideBtn->setEnabled(enabled); -} - -//-------------------------------------------------------------------------- -LLToast::~LLToast() -{ - if(LLApp::isQuitting()) - { - mOnFadeSignal.disconnect_all_slots(); - mOnDeleteToastSignal.disconnect_all_slots(); - mOnToastDestroyedSignal.disconnect_all_slots(); - mOnToastHoverSignal.disconnect_all_slots(); - mToastMouseEnterSignal.disconnect_all_slots(); - mToastMouseLeaveSignal.disconnect_all_slots(); - } - else - { - mOnToastDestroyedSignal(this); - } - - if (isModal()) - { - std::list<LLToast*>::iterator iter = std::find(sModalToastsList.begin(), sModalToastsList.end(), this); - if (iter != sModalToastsList.end()) - { - sModalToastsList.erase(iter); - } - } -} - -//-------------------------------------------------------------------------- -void LLToast::hide() -{ - if (!mIsHidden) - { - setVisible(false); - setFading(false); - mTimer->stop(); - mIsHidden = true; - mOnFadeSignal(this); - } -} - -/*virtual*/ -void LLToast::setFocus(bool b) -{ - if (b - && !hasFocus() - && mPanel - && mWrapperPanel - && !mWrapperPanel->getChildList()->empty()) - { - LLModalDialog::setFocus(true); - // mostly for buttons - mPanel->setFocus(true); - } - else - { - LLModalDialog::setFocus(b); - } -} - -void LLToast::onFocusLost() -{ - if(mWrapperPanel && !isBackgroundVisible()) - { - // Lets make wrapper panel behave like a floater - updateTransparency(); - } -} - -void LLToast::onFocusReceived() -{ - if(mWrapperPanel && !isBackgroundVisible()) - { - // Lets make wrapper panel behave like a floater - updateTransparency(); - } -} - -void LLToast::setLifetime(S32 seconds) -{ - mToastLifetime = seconds; -} - -void LLToast::setFadingTime(S32 seconds) -{ - mToastFadingTime = seconds; -} - -void LLToast::closeToast() -{ - mOnDeleteToastSignal(this); - - setSoundFlags(SILENT); - - closeFloater(); -} - -S32 LLToast::getTopPad() -{ - if(mWrapperPanel) - { - return getRect().getHeight() - mWrapperPanel->getRect().getHeight(); - } - return 0; -} - -S32 LLToast::getRightPad() -{ - if(mWrapperPanel) - { - return getRect().getWidth() - mWrapperPanel->getRect().getWidth(); - } - return 0; -} - -//-------------------------------------------------------------------------- -void LLToast::setCanFade(bool can_fade) -{ - mCanFade = can_fade; - if(!mCanFade) - { - mTimer->stop(); - } -} - -//-------------------------------------------------------------------------- -void LLToast::expire() -{ - if (mCanFade) - { - if (mIsFading) - { - // Fade timer expired. Time to hide. - hide(); - } - else - { - // "Life" time has ended. Time to fade. - setFading(true); - mTimer->restart(); - } - } -} - -void LLToast::setFading(bool transparent) -{ - mIsFading = transparent; - updateTransparency(); - - if (transparent) - { - mTimer->setPeriod(mToastFadingTime); - } - else - { - mTimer->setPeriod(mToastLifetime); - } -} - -F32 LLToast::getTimeLeftToLive() -{ - F32 time_to_live = mTimer->getRemainingTimeF32(); - - if (!mIsFading) - { - time_to_live += mToastFadingTime; - } - - return time_to_live; -} -//-------------------------------------------------------------------------- - -void LLToast::reshapeToPanel() -{ - LLPanel* panel = getPanel(); - if(!panel) - return; - - LLRect panel_rect = panel->getLocalRect(); - panel->setShape(panel_rect); - - LLRect toast_rect = getRect(); - - toast_rect.setLeftTopAndSize(toast_rect.mLeft, toast_rect.mTop, - panel_rect.getWidth() + getRightPad(), panel_rect.getHeight() + getTopPad()); - setShape(toast_rect); -} - -void LLToast::insertPanel(LLPanel* panel) -{ - mPanel = panel; - mWrapperPanel->addChild(panel); - reshapeToPanel(); -} - -//-------------------------------------------------------------------------- -void LLToast::draw() -{ - LLFloater::draw(); - - if(!isBackgroundVisible()) - { - // Floater background is invisible, lets make wrapper panel look like a - // floater - draw shadow. - drawShadow(mWrapperPanel); - - // Shadow will probably overlap close button, lets redraw the button - if(mHideBtn) - { - drawChild(mHideBtn); - } - } -} - -//-------------------------------------------------------------------------- -void LLToast::setVisible(bool show) -{ - if(mIsHidden) - { - // this toast is invisible after fade until its ScreenChannel will allow it - // - // (EXT-1849) according to this bug a toast can be resurrected from - // invisible state if it faded during a teleportation - // then it fades a second time and causes a crash - return; - } - - if (show && getVisible()) - { - return; - } - - if(show) - { - if(!mTimer->getStarted() && mCanFade) - { - mTimer->start(); - } - } - else - { - //hide "hide" button in case toast was hidden without mouse_leave - if(mHideBtn) - mHideBtn->setVisible(show); - } - LLFloater::setVisible(show); - if (mPanel - && !mPanel->isDead() - && mWrapperPanel - && !mWrapperPanel->getChildList()->empty() - // LLInspectToast can take over, but LLToast still appears to act like a data storage - && mPanel->getParent() == mWrapperPanel - ) - { - mPanel->setVisible(show); - } -} - -void LLToast::updateHoveredState() -{ - S32 x, y; - LLUI::getInstance()->getMousePositionScreen(&x, &y); - - LLRect panel_rc = mWrapperPanel->calcScreenRect(); - LLRect button_rc; - if(mHideBtn) - { - button_rc = mHideBtn->calcScreenRect(); - } - - if (!panel_rc.pointInRect(x, y) && !button_rc.pointInRect(x, y)) - { - // mouse is not over this toast - mIsHovered = false; - } - else - { - bool is_overlapped_by_other_floater = false; - - const child_list_t* child_list = gFloaterView->getChildList(); - - // find this toast in gFloaterView child list to check whether any floater - // with higher Z-order is visible under the mouse pointer overlapping this toast - child_list_const_reverse_iter_t r_iter = std::find(child_list->rbegin(), child_list->rend(), this); - if (r_iter != child_list->rend()) - { - // skip this toast and proceed to views above in Z-order - for (++r_iter; r_iter != child_list->rend(); ++r_iter) - { - LLView* view = *r_iter; - is_overlapped_by_other_floater = view->isInVisibleChain() && view->calcScreenRect().pointInRect(x, y); - if (is_overlapped_by_other_floater) - { - break; - } - } - } - - mIsHovered = !is_overlapped_by_other_floater; - } - - LLToastLifeTimer* timer = getTimer(); - - if (timer) - { - // Started timer means the mouse had left the toast previously. - // If toast is hovered in the current frame we should handle - // a mouse enter event. - if(timer->getStarted() && mIsHovered) - { - mOnToastHoverSignal(this, MOUSE_ENTER); - - updateTransparency(); - - //toasts fading is management by Screen Channel - - sendChildToFront(mHideBtn); - if(mHideBtn && mHideBtn->getEnabled()) - { - mHideBtn->setVisible(true); - } - - mToastMouseEnterSignal(this, getValue()); - } - // Stopped timer means the mouse had entered the toast previously. - // If the toast is not hovered in the current frame we should handle - // a mouse leave event. - else if(!timer->getStarted() && !mIsHovered) - { - mOnToastHoverSignal(this, MOUSE_LEAVE); - - updateTransparency(); - - //toasts fading is management by Screen Channel - - if(mHideBtn && mHideBtn->getEnabled()) - { - if( mHideBtnPressed ) - { - mHideBtnPressed = false; - return; - } - mHideBtn->setVisible(false); - } - - mToastMouseLeaveSignal(this, getValue()); - } - } -} - -void LLToast::setBackgroundOpaque(bool b) -{ - if(mWrapperPanel && !isBackgroundVisible()) - { - mWrapperPanel->setBackgroundOpaque(b); - } - else - { - LLModalDialog::setBackgroundOpaque(b); - } -} - -void LLToast::updateTransparency() -{ - ETypeTransparency transparency_type; - - if (mCanFade) - { - // Notification toasts (including IM/chat toasts) change their transparency on hover. - if (isHovered()) - { - transparency_type = TT_ACTIVE; - } - else - { - transparency_type = mIsFading ? TT_FADING : TT_INACTIVE; - } - } - else - { - // Transparency of alert toasts depends on focus. - transparency_type = hasFocus() ? TT_ACTIVE : TT_INACTIVE; - } - - LLFloater::updateTransparency(transparency_type); -} - -void LLNotificationsUI::LLToast::stopTimer() -{ - if(mCanFade) - { - setFading(false); - mTimer->stop(); - } -} - -void LLNotificationsUI::LLToast::startTimer() -{ - if(mCanFade) - { - setFading(false); - mTimer->start(); - } -} - -//-------------------------------------------------------------------------- - -bool LLToast::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if(mHideBtn && mHideBtn->getEnabled()) - { - mHideBtnPressed = mHideBtn->getRect().pointInRect(x, y); - } - - return LLModalDialog::handleMouseDown(x, y, mask); -} - -//-------------------------------------------------------------------------- -bool LLToast::isNotificationValid() -{ - if(mNotification) - { - return !mNotification->isCancelled(); - } - return false; -} - -//-------------------------------------------------------------------------- - -S32 LLToast::notifyParent(const LLSD& info) -{ - if (info.has("action") && "hide_toast" == info["action"].asString()) - { - hide(); - return 1; - } - - return LLModalDialog::notifyParent(info); -} - -//static -void LLToast::updateClass() -{ - for (auto& toast : LLInstanceTracker<LLToast>::instance_snapshot()) - { - toast.updateHoveredState(); - } -} - -// static -void LLToast::cleanupToasts() -{ - LLInstanceTracker<LLToast>::instance_snapshot().deleteAll(); -} - +/**
+ * @file lltoast.cpp
+ * @brief This class implements a placeholder for any notification panel.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "lltoast.h"
+
+#include "llbutton.h"
+#include "llfocusmgr.h"
+#include "llnotifications.h"
+#include "llviewercontrol.h"
+
+using namespace LLNotificationsUI;
+std::list<LLToast*> LLToast::sModalToastsList;
+
+//--------------------------------------------------------------------------
+LLToastLifeTimer::LLToastLifeTimer(LLToast* toast, F32 period)
+ : mToast(toast),
+ LLEventTimer(period)
+{
+}
+
+/*virtual*/
+bool LLToastLifeTimer::tick()
+{
+ if (mEventTimer.hasExpired())
+ {
+ mToast->expire();
+ }
+ return false;
+}
+
+void LLToastLifeTimer::stop()
+{
+ mEventTimer.stop();
+}
+
+void LLToastLifeTimer::start()
+{
+ mEventTimer.start();
+}
+
+void LLToastLifeTimer::restart()
+{
+ mEventTimer.reset();
+}
+
+bool LLToastLifeTimer::getStarted()
+{
+ return mEventTimer.getStarted();
+}
+
+void LLToastLifeTimer::setPeriod(F32 period)
+{
+ mPeriod = period;
+}
+
+F32 LLToastLifeTimer::getRemainingTimeF32()
+{
+ F32 et = mEventTimer.getElapsedTimeF32();
+ if (!getStarted() || et > mPeriod) return 0.0f;
+ return mPeriod - et;
+}
+
+//--------------------------------------------------------------------------
+LLToast::Params::Params()
+: can_fade("can_fade", true),
+ can_be_stored("can_be_stored", true),
+ is_modal("is_modal", false),
+ is_tip("is_tip", false),
+ enable_hide_btn("enable_hide_btn", true),
+ force_show("force_show", false),
+ force_store("force_store", false),
+ fading_time_secs("fading_time_secs", gSavedSettings.getS32("ToastFadingTime")),
+ lifetime_secs("lifetime_secs", gSavedSettings.getS32("NotificationToastLifeTime"))
+{};
+
+LLToast::LLToast(const LLToast::Params& p)
+: LLModalDialog(LLSD(), p.is_modal),
+ mToastLifetime(p.lifetime_secs),
+ mToastFadingTime(p.fading_time_secs),
+ mNotificationID(p.notif_id),
+ mSessionID(p.session_id),
+ mCanFade(p.can_fade),
+ mCanBeStored(p.can_be_stored),
+ mHideBtnEnabled(p.enable_hide_btn),
+ mHideBtn(NULL),
+ mPanel(NULL),
+ mNotification(p.notification),
+ mIsHidden(false),
+ mHideBtnPressed(false),
+ mIsTip(p.is_tip),
+ mWrapperPanel(NULL),
+ mIsFading(false),
+ mIsHovered(false)
+{
+ mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs));
+
+ buildFromFile("panel_toast.xml");
+
+ setCanDrag(false);
+
+ mWrapperPanel = getChild<LLPanel>("wrapper_panel");
+
+ setBackgroundOpaque(true); // *TODO: obsolete
+ updateTransparency();
+
+ if(p.panel())
+ {
+ insertPanel(p.panel);
+ }
+
+ if(mHideBtnEnabled)
+ {
+ mHideBtn = getChild<LLButton>("hide_btn");
+ mHideBtn->setClickedCallback(boost::bind(&LLToast::hide,this));
+ }
+
+ // init callbacks if present
+ if(!p.on_delete_toast().empty())
+ {
+ mOnDeleteToastSignal.connect(p.on_delete_toast());
+ }
+
+ if (isModal())
+ {
+ sModalToastsList.push_front(this);
+ }
+}
+
+void LLToast::reshape(S32 width, S32 height, bool called_from_parent)
+{
+ // We shouldn't use reshape from LLModalDialog since it changes toasts position.
+ // Toasts position should be controlled only by toast screen channel, see LLScreenChannelBase.
+ // see EXT-8044
+ LLFloater::reshape(width, height, called_from_parent);
+}
+
+//--------------------------------------------------------------------------
+bool LLToast::postBuild()
+{
+ if(!mCanFade)
+ {
+ mTimer->stop();
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setHideButtonEnabled(bool enabled)
+{
+ if(mHideBtn)
+ mHideBtn->setEnabled(enabled);
+}
+
+//--------------------------------------------------------------------------
+LLToast::~LLToast()
+{
+ if(LLApp::isQuitting())
+ {
+ mOnFadeSignal.disconnect_all_slots();
+ mOnDeleteToastSignal.disconnect_all_slots();
+ mOnToastDestroyedSignal.disconnect_all_slots();
+ mOnToastHoverSignal.disconnect_all_slots();
+ mToastMouseEnterSignal.disconnect_all_slots();
+ mToastMouseLeaveSignal.disconnect_all_slots();
+ }
+ else
+ {
+ mOnToastDestroyedSignal(this);
+ }
+
+ if (isModal())
+ {
+ std::list<LLToast*>::iterator iter = std::find(sModalToastsList.begin(), sModalToastsList.end(), this);
+ if (iter != sModalToastsList.end())
+ {
+ sModalToastsList.erase(iter);
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLToast::hide()
+{
+ if (!mIsHidden)
+ {
+ setVisible(false);
+ setFading(false);
+ mTimer->stop();
+ mIsHidden = true;
+ mOnFadeSignal(this);
+ }
+}
+
+/*virtual*/
+void LLToast::setFocus(bool b)
+{
+ if (b
+ && !hasFocus()
+ && mPanel
+ && mWrapperPanel
+ && !mWrapperPanel->getChildList()->empty())
+ {
+ LLModalDialog::setFocus(true);
+ // mostly for buttons
+ mPanel->setFocus(true);
+ }
+ else
+ {
+ LLModalDialog::setFocus(b);
+ }
+}
+
+void LLToast::onFocusLost()
+{
+ if(mWrapperPanel && !isBackgroundVisible())
+ {
+ // Lets make wrapper panel behave like a floater
+ updateTransparency();
+ }
+}
+
+void LLToast::onFocusReceived()
+{
+ if(mWrapperPanel && !isBackgroundVisible())
+ {
+ // Lets make wrapper panel behave like a floater
+ updateTransparency();
+ }
+}
+
+void LLToast::setLifetime(S32 seconds)
+{
+ mToastLifetime = seconds;
+}
+
+void LLToast::setFadingTime(S32 seconds)
+{
+ mToastFadingTime = seconds;
+}
+
+void LLToast::closeToast()
+{
+ mOnDeleteToastSignal(this);
+
+ setSoundFlags(SILENT);
+
+ closeFloater();
+}
+
+S32 LLToast::getTopPad()
+{
+ if(mWrapperPanel)
+ {
+ return getRect().getHeight() - mWrapperPanel->getRect().getHeight();
+ }
+ return 0;
+}
+
+S32 LLToast::getRightPad()
+{
+ if(mWrapperPanel)
+ {
+ return getRect().getWidth() - mWrapperPanel->getRect().getWidth();
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setCanFade(bool can_fade)
+{
+ mCanFade = can_fade;
+ if(!mCanFade)
+ {
+ mTimer->stop();
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLToast::expire()
+{
+ if (mCanFade)
+ {
+ if (mIsFading)
+ {
+ // Fade timer expired. Time to hide.
+ hide();
+ }
+ else
+ {
+ // "Life" time has ended. Time to fade.
+ setFading(true);
+ mTimer->restart();
+ }
+ }
+}
+
+void LLToast::setFading(bool transparent)
+{
+ mIsFading = transparent;
+ updateTransparency();
+
+ if (transparent)
+ {
+ mTimer->setPeriod(mToastFadingTime);
+ }
+ else
+ {
+ mTimer->setPeriod(mToastLifetime);
+ }
+}
+
+F32 LLToast::getTimeLeftToLive()
+{
+ F32 time_to_live = mTimer->getRemainingTimeF32();
+
+ if (!mIsFading)
+ {
+ time_to_live += mToastFadingTime;
+ }
+
+ return time_to_live;
+}
+//--------------------------------------------------------------------------
+
+void LLToast::reshapeToPanel()
+{
+ LLPanel* panel = getPanel();
+ if(!panel)
+ return;
+
+ LLRect panel_rect = panel->getLocalRect();
+ panel->setShape(panel_rect);
+
+ LLRect toast_rect = getRect();
+
+ toast_rect.setLeftTopAndSize(toast_rect.mLeft, toast_rect.mTop,
+ panel_rect.getWidth() + getRightPad(), panel_rect.getHeight() + getTopPad());
+ setShape(toast_rect);
+}
+
+void LLToast::insertPanel(LLPanel* panel)
+{
+ mPanel = panel;
+ mWrapperPanel->addChild(panel);
+ reshapeToPanel();
+}
+
+//--------------------------------------------------------------------------
+void LLToast::draw()
+{
+ LLFloater::draw();
+
+ if(!isBackgroundVisible())
+ {
+ // Floater background is invisible, lets make wrapper panel look like a
+ // floater - draw shadow.
+ drawShadow(mWrapperPanel);
+
+ // Shadow will probably overlap close button, lets redraw the button
+ if(mHideBtn)
+ {
+ drawChild(mHideBtn);
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setVisible(bool show)
+{
+ if(mIsHidden)
+ {
+ // this toast is invisible after fade until its ScreenChannel will allow it
+ //
+ // (EXT-1849) according to this bug a toast can be resurrected from
+ // invisible state if it faded during a teleportation
+ // then it fades a second time and causes a crash
+ return;
+ }
+
+ if (show && getVisible())
+ {
+ return;
+ }
+
+ if(show)
+ {
+ if(!mTimer->getStarted() && mCanFade)
+ {
+ mTimer->start();
+ }
+ }
+ else
+ {
+ //hide "hide" button in case toast was hidden without mouse_leave
+ if(mHideBtn)
+ mHideBtn->setVisible(show);
+ }
+ LLFloater::setVisible(show);
+ if (mPanel
+ && !mPanel->isDead()
+ && mWrapperPanel
+ && !mWrapperPanel->getChildList()->empty()
+ // LLInspectToast can take over, but LLToast still appears to act like a data storage
+ && mPanel->getParent() == mWrapperPanel
+ )
+ {
+ mPanel->setVisible(show);
+ }
+}
+
+void LLToast::updateHoveredState()
+{
+ S32 x, y;
+ LLUI::getInstance()->getMousePositionScreen(&x, &y);
+
+ LLRect panel_rc = mWrapperPanel->calcScreenRect();
+ LLRect button_rc;
+ if(mHideBtn)
+ {
+ button_rc = mHideBtn->calcScreenRect();
+ }
+
+ if (!panel_rc.pointInRect(x, y) && !button_rc.pointInRect(x, y))
+ {
+ // mouse is not over this toast
+ mIsHovered = false;
+ }
+ else
+ {
+ bool is_overlapped_by_other_floater = false;
+
+ const child_list_t* child_list = gFloaterView->getChildList();
+
+ // find this toast in gFloaterView child list to check whether any floater
+ // with higher Z-order is visible under the mouse pointer overlapping this toast
+ child_list_const_reverse_iter_t r_iter = std::find(child_list->rbegin(), child_list->rend(), this);
+ if (r_iter != child_list->rend())
+ {
+ // skip this toast and proceed to views above in Z-order
+ for (++r_iter; r_iter != child_list->rend(); ++r_iter)
+ {
+ LLView* view = *r_iter;
+ is_overlapped_by_other_floater = view->isInVisibleChain() && view->calcScreenRect().pointInRect(x, y);
+ if (is_overlapped_by_other_floater)
+ {
+ break;
+ }
+ }
+ }
+
+ mIsHovered = !is_overlapped_by_other_floater;
+ }
+
+ LLToastLifeTimer* timer = getTimer();
+
+ if (timer)
+ {
+ // Started timer means the mouse had left the toast previously.
+ // If toast is hovered in the current frame we should handle
+ // a mouse enter event.
+ if(timer->getStarted() && mIsHovered)
+ {
+ mOnToastHoverSignal(this, MOUSE_ENTER);
+
+ updateTransparency();
+
+ //toasts fading is management by Screen Channel
+
+ sendChildToFront(mHideBtn);
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ mHideBtn->setVisible(true);
+ }
+
+ mToastMouseEnterSignal(this, getValue());
+ }
+ // Stopped timer means the mouse had entered the toast previously.
+ // If the toast is not hovered in the current frame we should handle
+ // a mouse leave event.
+ else if(!timer->getStarted() && !mIsHovered)
+ {
+ mOnToastHoverSignal(this, MOUSE_LEAVE);
+
+ updateTransparency();
+
+ //toasts fading is management by Screen Channel
+
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ if( mHideBtnPressed )
+ {
+ mHideBtnPressed = false;
+ return;
+ }
+ mHideBtn->setVisible(false);
+ }
+
+ mToastMouseLeaveSignal(this, getValue());
+ }
+ }
+}
+
+void LLToast::setBackgroundOpaque(bool b)
+{
+ if(mWrapperPanel && !isBackgroundVisible())
+ {
+ mWrapperPanel->setBackgroundOpaque(b);
+ }
+ else
+ {
+ LLModalDialog::setBackgroundOpaque(b);
+ }
+}
+
+void LLToast::updateTransparency()
+{
+ ETypeTransparency transparency_type;
+
+ if (mCanFade)
+ {
+ // Notification toasts (including IM/chat toasts) change their transparency on hover.
+ if (isHovered())
+ {
+ transparency_type = TT_ACTIVE;
+ }
+ else
+ {
+ transparency_type = mIsFading ? TT_FADING : TT_INACTIVE;
+ }
+ }
+ else
+ {
+ // Transparency of alert toasts depends on focus.
+ transparency_type = hasFocus() ? TT_ACTIVE : TT_INACTIVE;
+ }
+
+ LLFloater::updateTransparency(transparency_type);
+}
+
+void LLNotificationsUI::LLToast::stopTimer()
+{
+ if(mCanFade)
+ {
+ setFading(false);
+ mTimer->stop();
+ }
+}
+
+void LLNotificationsUI::LLToast::startTimer()
+{
+ if(mCanFade)
+ {
+ setFading(false);
+ mTimer->start();
+ }
+}
+
+//--------------------------------------------------------------------------
+
+bool LLToast::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ mHideBtnPressed = mHideBtn->getRect().pointInRect(x, y);
+ }
+
+ return LLModalDialog::handleMouseDown(x, y, mask);
+}
+
+//--------------------------------------------------------------------------
+bool LLToast::isNotificationValid()
+{
+ if(mNotification)
+ {
+ return !mNotification->isCancelled();
+ }
+ return false;
+}
+
+//--------------------------------------------------------------------------
+
+S32 LLToast::notifyParent(const LLSD& info)
+{
+ if (info.has("action") && "hide_toast" == info["action"].asString())
+ {
+ hide();
+ return 1;
+ }
+
+ return LLModalDialog::notifyParent(info);
+}
+
+//static
+void LLToast::updateClass()
+{
+ for (auto& toast : LLInstanceTracker<LLToast>::instance_snapshot())
+ {
+ toast.updateHoveredState();
+ }
+}
+
+// static
+void LLToast::cleanupToasts()
+{
+ LLInstanceTracker<LLToast>::instance_snapshot().deleteAll();
+}
+
|
