Fixed low bug EXT-4246 - Close button on notification toast is larger than host spot.

Close button is partially positioned out of toast(floater). Usually, hovering or clicking
that "outer" part of the button can not be handled. The workaround is to position the button
on the floater and make the floater background invisible. Now close button is properly handled,
but toast is transparent. To fix this i added wrapper_panel that looks and behaves like a floater.

--HG--
branch : product-engine
meow-7.2.2
Dmitry Zaporozhan 2010-02-17 16:00:28 +02:00
parent 619415a99a
commit 4b161b8839
5 changed files with 197 additions and 65 deletions

View File

@ -282,7 +282,7 @@ void LLNearbyChatScreenChannel::showToastsBottom()
gFloaterView->sendChildToBack(toast);
}
bottom = toast->getRect().mTop;
bottom = toast->getRect().mTop - toast->getTopPad();
}
}
}

View File

@ -79,17 +79,12 @@ LLScreenChannelBase::~LLScreenChannelBase()
bool LLScreenChannelBase::isHovering()
{
bool res = mHoveredToast != NULL;
if (!res)
if (!mHoveredToast)
{
return res;
return false;
}
S32 x, y;
mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
gViewerWindow->getCurrentMouseY(), &x, &y);
res = mHoveredToast->pointInView(x, y) == TRUE;
return res;
return mHoveredToast->isHovered();
}
void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
@ -479,7 +474,8 @@ void LLScreenChannel::showToastsBottom()
{
if(it != mToastList.rbegin())
{
bottom = (*(it-1)).toast->getRect().mTop;
LLToast* toast = (*(it-1)).toast;
bottom = toast->getRect().mTop - toast->getTopPad();
toast_margin = gSavedSettings.getS32("ToastGap");
}
@ -777,23 +773,16 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
{
// because of LLViewerWindow::updateUI() that NOT ALWAYS calls onMouseEnter BEFORE onMouseLeave
// we must check hovering directly to prevent incorrect setting for hovering in a channel
S32 x,y;
if (mouse_enter)
{
toast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
gViewerWindow->getCurrentMouseY(), &x, &y);
bool hover = toast->pointInView(x, y) == TRUE;
if (hover)
if (toast->isHovered())
{
mHoveredToast = toast;
}
}
else if (mHoveredToast != NULL)
{
mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
gViewerWindow->getCurrentMouseY(), &x, &y);
bool hover = mHoveredToast->pointInView(x, y) == TRUE;
if (!hover)
if (!mHoveredToast->isHovered())
{
mHoveredToast = NULL;
}

View File

@ -68,12 +68,17 @@ LLToast::LLToast(const LLToast::Params& p)
mNotification(p.notification),
mIsHidden(false),
mHideBtnPressed(false),
mIsTip(p.is_tip)
mIsTip(p.is_tip),
mWrapperPanel(NULL)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "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);
@ -83,6 +88,8 @@ LLToast::LLToast(const LLToast::Params& p)
{
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
@ -174,6 +181,42 @@ void LLToast::hide()
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)
{
@ -199,22 +242,21 @@ void LLToast::reshapeToPanel()
if(!panel)
return;
LLRect panel_rect;
LLRect panel_rect = panel->getRect();
panel_rect = panel->getRect();
reshape(panel_rect.getWidth(), panel_rect.getHeight());
panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
panel->setRect(panel_rect);
panel->setShape(panel_rect);
LLRect toast_rect = getRect();
toast_rect.setLeftTopAndSize(toast_rect.mLeft,toast_rect.mTop,panel_rect.getWidth(), panel_rect.getHeight());
setRect(toast_rect);
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)
{
addChild(panel);
mWrapperPanel->addChild(panel);
reshapeToPanel();
}
@ -227,6 +269,19 @@ 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);
}
}
}
//--------------------------------------------------------------------------
@ -261,43 +316,78 @@ void LLToast::setVisible(BOOL show)
}
}
//--------------------------------------------------------------------------
void LLToast::onMouseEnter(S32 x, S32 y, MASK mask)
void LLToast::onToastMouseEnter()
{
mOnToastHoverSignal(this, MOUSE_ENTER);
setBackgroundOpaque(TRUE);
//toasts fading is management by Screen Channel
sendChildToFront(mHideBtn);
if(mHideBtn && mHideBtn->getEnabled())
mHideBtn->setVisible(TRUE);
mOnMouseEnterSignal(this);
LLModalDialog::onMouseEnter(x, y, mask);
}
//--------------------------------------------------------------------------
void LLToast::onMouseLeave(S32 x, S32 y, MASK mask)
{
mOnToastHoverSignal(this, MOUSE_LEAVE);
//toasts fading is management by Screen Channel
if(mHideBtn && mHideBtn->getEnabled())
LLRect panel_rc = mWrapperPanel->calcScreenRect();
LLRect button_rc;
if(mHideBtn)
{
if( mHideBtnPressed )
{
mHideBtnPressed = false;
return;
}
mHideBtn->setVisible(FALSE);
button_rc = mHideBtn->calcScreenRect();
}
LLModalDialog::onMouseLeave(x, y, mask);
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()
{
@ -315,6 +405,13 @@ void LLNotificationsUI::LLToast::startFading()
}
}
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)

View File

@ -86,8 +86,6 @@ public:
// Toast handlers
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
//Fading
@ -97,6 +95,7 @@ public:
/** Start fading timer */
virtual void startFading();
bool isHovered();
// Operating with toasts
// insert a panel to a toast
@ -118,10 +117,22 @@ public:
virtual void draw();
//
virtual void setVisible(BOOL show);
/*virtual*/ void setBackgroundOpaque(BOOL b);
//
virtual void hide();
/*virtual*/ void onFocusLost();
/*virtual*/ void onFocusReceived();
/**
* Returns padding between floater top and wrapper_panel top.
* This padding should be taken into account when positioning or reshaping toasts
*/
S32 getTopPad();
S32 getRightPad();
// get/set Toast's flags or states
// get information whether the notification corresponding to the toast is valid or not
@ -154,9 +165,15 @@ public:
toast_hover_check_signal_t mOnToastHoverSignal;
boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHoverSignal.connect(cb); }
boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseEnterSignal.connect(cb); };
boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseLeaveSignal.connect(cb); };
private:
void onToastMouseEnter();
void onToastMouseLeave();
void handleTipToastClick(S32 x, S32 y, MASK mask);
// check timer
@ -168,6 +185,8 @@ private:
LLUUID mSessionID;
LLNotificationPtr mNotification;
LLPanel* mWrapperPanel;
// timer counts a lifetime of a toast
LLTimer mTimer;
F32 mToastLifetime; // in seconds
@ -184,6 +203,9 @@ private:
bool mHideBtnPressed;
bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
bool mIsTip;
commit_signal_t mToastMouseEnterSignal;
commit_signal_t mToastMouseLeaveSignal;
};
}

View File

@ -3,17 +3,25 @@
<!-- Don't remove floater's height! It is needed for Overflow and Start-Up toasts!-->
<!--
This floater is invisible. To make toast look like a floater we render wrapper_panel
like a floater(draw shadows and so on). This is done with one purpose - make close button
look like it is positioned out of floater and able to accept mouse clicks (see EXT-4246)
-->
<floater
legacy_header_height="18"
legacy_header_height="0"
header_height="0"
name="toast"
title=""
visible="false"
layout="topleft"
height="40"
width="305"
height="47"
width="310"
left="0"
top="0"
follows="right|bottom"
background_visible="false"
bg_opaque_image="Toast_Over"
bg_alpha_image="Toast_Background"
can_minimize="false"
@ -27,6 +35,21 @@
drop_shadow_visible = "false"
border = "false"
>
<panel
background_opaque="false"
border_visible="false"
background_visible="true"
bg_opaque_image="Toast_Over"
bg_alpha_image="Toast_Background"
label="wrapper_panel"
layout="topleft"
left="0"
name="wrapper_panel"
top="7"
height="40"
follows="all"
translate="false"
width="305">
<!-- Don't remove this wiget! It is needed for Overflow and Start-Up toasts!-->
<text
clip_partial="true"
@ -46,10 +69,11 @@
width="260">
Toast text;
</text>
</panel>
<button
layout="topleft"
top="-14"
left="293"
top="0"
right="310"
width="17"
height="17"
follows="top|right"