summaryrefslogtreecommitdiff
path: root/indra/newview/lltoast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lltoast.cpp')
-rw-r--r--indra/newview/lltoast.cpp427
1 files changed, 427 insertions, 0 deletions
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
new file mode 100644
index 0000000000..c3090cb1fc
--- /dev/null
+++ b/indra/newview/lltoast.cpp
@@ -0,0 +1,427 @@
+/**
+ * @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;
+
+/*virtual*/
+BOOL LLToastLifeTimer::tick()
+{
+ if (mEventTimer.hasExpired())
+ {
+ mToast->expire();
+ }
+ return FALSE;
+}
+
+//--------------------------------------------------------------------------
+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),
+ mPanel(p.panel),
+ 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),
+ mNotification(p.notification),
+ mIsHidden(false),
+ mHideBtnPressed(false),
+ mIsTip(p.is_tip),
+ mWrapperPanel(NULL)
+{
+ mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs));
+
+ buildFromFile("panel_toast.xml", NULL);
+
+ setCanDrag(FALSE);
+
+ mWrapperPanel = getChild<LLPanel>("wrapper_panel");
+ mWrapperPanel->setMouseEnterCallback(boost::bind(&LLToast::onToastMouseEnter, this));
+ mWrapperPanel->setMouseLeaveCallback(boost::bind(&LLToast::onToastMouseLeave, this));
+
+ if(mPanel)
+ {
+ insertPanel(mPanel);
+ }
+
+ if(mHideBtnEnabled)
+ {
+ mHideBtn = getChild<LLButton>("hide_btn");
+ mHideBtn->setClickedCallback(boost::bind(&LLToast::hide,this));
+ mHideBtn->setMouseEnterCallback(boost::bind(&LLToast::onToastMouseEnter, this));
+ mHideBtn->setMouseLeaveCallback(boost::bind(&LLToast::onToastMouseLeave, this));
+ }
+
+ // init callbacks if present
+ if(!p.on_delete_toast().empty())
+ mOnDeleteToastSignal.connect(p.on_delete_toast());
+
+ // *TODO: This signal doesn't seem to be used at all.
+ if(!p.on_mouse_enter().empty())
+ mOnMouseEnterSignal.connect(p.on_mouse_enter());
+}
+
+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()
+{
+ mOnToastDestroyedSignal(this);
+}
+
+//--------------------------------------------------------------------------
+void LLToast::hide()
+{
+ setVisible(FALSE);
+ mTimer->stop();
+ mIsHidden = true;
+ mOnFadeSignal(this);
+}
+
+void LLToast::onFocusLost()
+{
+ if(mWrapperPanel && !isBackgroundVisible())
+ {
+ // Lets make wrapper panel behave like a floater
+ setBackgroundOpaque(FALSE);
+ }
+}
+
+void LLToast::onFocusReceived()
+{
+ if(mWrapperPanel && !isBackgroundVisible())
+ {
+ // Lets make wrapper panel behave like a floater
+ setBackgroundOpaque(TRUE);
+ }
+}
+
+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 toast has fade property - hide it
+ if(mCanFade)
+ {
+ hide();
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void LLToast::reshapeToPanel()
+{
+ LLPanel* panel = getPanel();
+ if(!panel)
+ return;
+
+ LLRect panel_rect = panel->getRect();
+
+ panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
+ 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)
+{
+ 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);
+ }
+ }
+
+ // if timer started and remaining time <= fading time
+ if (mTimer->getStarted() && (mToastLifetime
+ - mTimer->getEventTimer().getElapsedTimeF32()) <= mToastFadingTime)
+ {
+ setBackgroundOpaque(FALSE);
+ }
+}
+
+//--------------------------------------------------------------------------
+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)
+ {
+ setBackgroundOpaque(TRUE);
+ if(!mTimer->getStarted() && mCanFade)
+ {
+ mTimer->start();
+ }
+ if (!getVisible())
+ {
+ LLModalDialog::setFrontmost(FALSE);
+ }
+ }
+ else
+ {
+ //hide "hide" button in case toast was hidden without mouse_leave
+ if(mHideBtn)
+ mHideBtn->setVisible(show);
+ }
+ LLFloater::setVisible(show);
+ if(mPanel)
+ {
+ if(!mPanel->isDead())
+ {
+ mPanel->setVisible(show);
+ }
+ }
+}
+
+void LLToast::onToastMouseEnter()
+{
+ LLRect panel_rc = mWrapperPanel->calcScreenRect();
+ LLRect button_rc;
+ if(mHideBtn)
+ {
+ button_rc = mHideBtn->calcScreenRect();
+ }
+
+ S32 x, y;
+ LLUI::getMousePositionScreen(&x, &y);
+
+ if(panel_rc.pointInRect(x, y) || button_rc.pointInRect(x, y))
+ {
+ mOnToastHoverSignal(this, MOUSE_ENTER);
+
+ setBackgroundOpaque(TRUE);
+
+ //toasts fading is management by Screen Channel
+
+ sendChildToFront(mHideBtn);
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ mHideBtn->setVisible(TRUE);
+ }
+ mOnMouseEnterSignal(this);
+ mToastMouseEnterSignal(this, getValue());
+ }
+}
+
+void LLToast::onToastMouseLeave()
+{
+ LLRect panel_rc = mWrapperPanel->calcScreenRect();
+ LLRect button_rc;
+ if(mHideBtn)
+ {
+ button_rc = mHideBtn->calcScreenRect();
+ }
+
+ S32 x, y;
+ LLUI::getMousePositionScreen(&x, &y);
+
+ if( !panel_rc.pointInRect(x, y) && !button_rc.pointInRect(x, y))
+ {
+ mOnToastHoverSignal(this, MOUSE_LEAVE);
+
+ //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 LLNotificationsUI::LLToast::stopFading()
+{
+ if(mCanFade)
+ {
+ stopTimer();
+ }
+}
+
+void LLNotificationsUI::LLToast::startFading()
+{
+ if(mCanFade)
+ {
+ resetTimer();
+ }
+}
+
+bool LLToast::isHovered()
+{
+ S32 x, y;
+ LLUI::getMousePositionScreen(&x, &y);
+ return mWrapperPanel->calcScreenRect().pointInRect(x, y);
+}
+
+//--------------------------------------------------------------------------
+
+BOOL LLToast::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ mHideBtnPressed = mHideBtn->getRect().pointInRect(x, y);
+ }
+
+ return LLFloater::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);
+}