diff options
Diffstat (limited to 'indra/llui/llmenubutton.cpp')
-rw-r--r-- | indra/llui/llmenubutton.cpp | 100 |
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; + } +} |