summaryrefslogtreecommitdiff
path: root/indra/llui/llmenubutton.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/llmenubutton.cpp')
-rw-r--r--indra/llui/llmenubutton.cpp100
1 files changed, 65 insertions, 35 deletions
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index c1b5efaa72..ac568a83e4 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -29,7 +29,7 @@
#include "llmenubutton.h"
// Linden library includes
-#include "llmenugl.h"
+#include "lltoggleablemenu.h"
#include "llstring.h"
#include "v4color.h"
@@ -44,22 +44,26 @@ LLMenuButton::Params::Params()
LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
: LLButton(p),
- mMenu(NULL),
- mMenuVisibleLastFrame(false),
+ mIsMenuShown(false),
mMenuPosition(MP_BOTTOM_LEFT)
{
std::string menu_filename = p.menu_filename;
if (!menu_filename.empty())
{
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
- if (!mMenu)
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (!menu)
{
llwarns << "Error loading menu_button menu" << llendl;
+ return;
}
- }
- updateMenuOrigin();
+ menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
+
+ mMenuHandle = menu->getHandle();
+
+ updateMenuOrigin();
+ }
}
boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
@@ -69,34 +73,34 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign
void LLMenuButton::hideMenu()
{
- if(!mMenu) return;
- mMenu->setVisible(FALSE);
+ if(mMenuHandle.isDead()) return;
+
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (menu)
+ {
+ menu->setVisible(FALSE);
+ }
}
-void LLMenuButton::setMenu(LLMenuGL* menu, EMenuPosition position /*MP_TOP_LEFT*/)
+LLToggleableMenu* LLMenuButton::getMenu()
{
- mMenu = menu;
- mMenuPosition = position;
+ return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
}
-void LLMenuButton::draw()
+void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/)
{
- //we save this off so next frame when we try to close it by
- //button click, and it hides menus before we get to it, we know
- mMenuVisibleLastFrame = mMenu && mMenu->getVisible();
-
- if (mMenuVisibleLastFrame)
- {
- setForcePressedState(true);
- }
+ if (!menu) return;
- LLButton::draw();
+ mMenuHandle = menu->getHandle();
+ mMenuPosition = position;
- setForcePressedState(false);
+ menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
}
BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
{
+ if (mMenuHandle.isDead()) return FALSE;
+
if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
{
// *HACK: We emit the mouse down signal to fire the callback bound to the
@@ -107,9 +111,10 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
return TRUE;
}
- if (mMenu && mMenu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
{
- mMenu->setVisible(FALSE);
+ menu->setVisible(FALSE);
return TRUE;
}
@@ -119,6 +124,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLButton::handleMouseDown(x, y, mask);
+
toggleMenu();
return TRUE;
@@ -126,28 +132,38 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
void LLMenuButton::toggleMenu()
{
- if(!mMenu) return;
+ if(mMenuHandle.isDead()) return;
+
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (!menu) return;
- if (mMenu->getVisible() || mMenuVisibleLastFrame)
+ // Store the button rectangle to toggle menu visibility if a mouse event
+ // occurred inside or outside the button rect.
+ menu->setButtonRect(this);
+
+ if (!menu->toggleVisibility() && mIsMenuShown)
{
- mMenu->setVisible(FALSE);
+ setForcePressedState(false);
+ mIsMenuShown = false;
}
else
{
- mMenu->buildDrawLabels();
- mMenu->arrangeAndClear();
- mMenu->updateParent(LLMenuGL::sMenuContainer);
+ menu->buildDrawLabels();
+ menu->arrangeAndClear();
+ menu->updateParent(LLMenuGL::sMenuContainer);
updateMenuOrigin();
- //mMenu->needsArrange(); //so it recalculates the visible elements
- LLMenuGL::showPopup(getParent(), mMenu, mX, mY);
+ LLMenuGL::showPopup(getParent(), menu, mX, mY);
+
+ setForcePressedState(true);
+ mIsMenuShown = true;
}
}
void LLMenuButton::updateMenuOrigin()
{
- if (!mMenu) return;
+ if (mMenuHandle.isDead()) return;
LLRect rect = getRect();
@@ -156,7 +172,7 @@ void LLMenuButton::updateMenuOrigin()
case MP_TOP_LEFT:
{
mX = rect.mLeft;
- mY = rect.mTop + mMenu->getRect().getHeight();
+ mY = rect.mTop + mMenuHandle.get()->getRect().getHeight();
break;
}
case MP_BOTTOM_LEFT:
@@ -167,3 +183,17 @@ void LLMenuButton::updateMenuOrigin()
}
}
}
+
+void LLMenuButton::onMenuVisibilityChange(const LLSD& param)
+{
+ bool new_visibility = param["visibility"].asBoolean();
+ bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean();
+
+ // Reset the button "pressed" state only if the menu is shown by this particular
+ // menu button (not any other control) and is not being closed by a click on the button.
+ if (!new_visibility && !is_closed_by_button_click && mIsMenuShown)
+ {
+ setForcePressedState(false);
+ mIsMenuShown = false;
+ }
+}