diff options
Diffstat (limited to 'indra/llui/llmenubutton.cpp')
-rw-r--r-- | indra/llui/llmenubutton.cpp | 492 |
1 files changed, 246 insertions, 246 deletions
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index e3cb35abc7..2f91dcb046 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -1,246 +1,246 @@ -/**
- * @file llbutton.cpp
- * @brief LLButton base class
- *
- * $LicenseInfo:firstyear=2001&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 "linden_common.h"
-
-#include "llmenubutton.h"
-
-// Linden library includes
-#include "lltoggleablemenu.h"
-#include "llstring.h"
-#include "v4color.h"
-
-static LLDefaultChildRegistry::Register<LLMenuButton> r("menu_button");
-
-void LLMenuButton::MenuPositions::declareValues()
-{
- declare("topleft", MP_TOP_LEFT);
- declare("topright", MP_TOP_RIGHT);
- declare("bottomleft", MP_BOTTOM_LEFT);
- declare("bottomright", MP_BOTTOM_RIGHT);
-}
-
-LLMenuButton::Params::Params()
-: menu_filename("menu_filename"),
- position("menu_position", MP_BOTTOM_LEFT)
-{
- addSynonym(position, "position");
-}
-
-
-LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
-: LLButton(p),
- mIsMenuShown(false),
- mMenuPosition(p.position),
- mOwnMenu(false)
-{
- std::string menu_filename = p.menu_filename;
-
- setMenu(menu_filename, mMenuPosition);
- updateMenuOrigin();
-}
-
-LLMenuButton::~LLMenuButton()
-{
- cleanup();
-}
-
-boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
-{
- return LLUICtrl::setMouseDownCallback(cb);
-}
-
-void LLMenuButton::hideMenu()
-{
- LLToggleableMenu* menu = getMenu();
- if (menu)
- {
- menu->setVisible(false);
- }
-}
-
-LLToggleableMenu* LLMenuButton::getMenu()
-{
- return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
-}
-
-void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/)
-{
- if (menu_filename.empty())
- {
- return;
- }
-
- llassert(LLMenuGL::sMenuContainer != NULL);
- LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
- if (!menu)
- {
- LL_WARNS() << "Error loading menu_button menu" << LL_ENDL;
- return;
- }
-
- setMenu(menu, position, true);
-}
-
-void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/)
-{
- if (!menu) return;
-
- cleanup(); // destroy the previous memnu if we own it
-
- mMenuHandle = menu->getHandle();
- mMenuPosition = position;
- mOwnMenu = take_ownership;
-
- menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
-}
-
-bool LLMenuButton::handleKeyHere(KEY key, MASK mask )
-{
- if (!getMenu()) 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
- // menu emerging event before actually displaying the menu. See STORM-263.
- LLUICtrl::handleMouseDown(-1, -1, MASK_NONE);
-
- toggleMenu();
- return true;
- }
-
- LLToggleableMenu* menu = getMenu();
- if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
- {
- menu->setVisible(false);
- return true;
- }
-
- return false;
-}
-
-bool LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
-{
- LLButton::handleMouseDown(x, y, mask);
-
- toggleMenu();
-
- return true;
-}
-
-void LLMenuButton::toggleMenu()
-{
- if (mValidateSignal && !(*mValidateSignal)(this, LLSD()))
- {
- return;
- }
-
- LLToggleableMenu* menu = getMenu();
- if (!menu) return;
-
- // 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)
- {
- setForcePressedState(false);
- mIsMenuShown = false;
- }
- else
- {
- menu->buildDrawLabels();
- menu->arrangeAndClear();
- menu->updateParent(LLMenuGL::sMenuContainer);
-
- updateMenuOrigin();
-
- LLMenuGL::showPopup(getParent(), menu, mX, mY);
-
- setForcePressedState(true);
- mIsMenuShown = true;
- }
-}
-
-void LLMenuButton::updateMenuOrigin()
-{
- LLToggleableMenu* menu = getMenu();
- if (!menu) return;
-
- LLRect rect = getRect();
-
- switch (mMenuPosition)
- {
- case MP_TOP_LEFT:
- {
- mX = rect.mLeft;
- mY = rect.mTop + menu->getRect().getHeight();
- break;
- }
- case MP_TOP_RIGHT:
- {
- const LLRect& menu_rect = menu->getRect();
- mX = rect.mRight - menu_rect.getWidth();
- mY = rect.mTop + menu_rect.getHeight();
- break;
- }
- case MP_BOTTOM_LEFT:
- {
- mX = rect.mLeft;
- mY = rect.mBottom;
- break;
- }
- case MP_BOTTOM_RIGHT:
- {
- const LLRect& menu_rect = menu->getRect();
- mX = rect.mRight - menu_rect.getWidth();
- mY = rect.mBottom;
- break;
- }
- }
-}
-
-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;
- }
-}
-
-void LLMenuButton::cleanup()
-{
- if (mMenuHandle.get() && mOwnMenu)
- {
- mMenuHandle.get()->die();
- }
-}
+/** + * @file llbutton.cpp + * @brief LLButton base class + * + * $LicenseInfo:firstyear=2001&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 "linden_common.h" + +#include "llmenubutton.h" + +// Linden library includes +#include "lltoggleablemenu.h" +#include "llstring.h" +#include "v4color.h" + +static LLDefaultChildRegistry::Register<LLMenuButton> r("menu_button"); + +void LLMenuButton::MenuPositions::declareValues() +{ + declare("topleft", MP_TOP_LEFT); + declare("topright", MP_TOP_RIGHT); + declare("bottomleft", MP_BOTTOM_LEFT); + declare("bottomright", MP_BOTTOM_RIGHT); +} + +LLMenuButton::Params::Params() +: menu_filename("menu_filename"), + position("menu_position", MP_BOTTOM_LEFT) +{ + addSynonym(position, "position"); +} + + +LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) +: LLButton(p), + mIsMenuShown(false), + mMenuPosition(p.position), + mOwnMenu(false) +{ + std::string menu_filename = p.menu_filename; + + setMenu(menu_filename, mMenuPosition); + updateMenuOrigin(); +} + +LLMenuButton::~LLMenuButton() +{ + cleanup(); +} + +boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) +{ + return LLUICtrl::setMouseDownCallback(cb); +} + +void LLMenuButton::hideMenu() +{ + LLToggleableMenu* menu = getMenu(); + if (menu) + { + menu->setVisible(false); + } +} + +LLToggleableMenu* LLMenuButton::getMenu() +{ + return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +} + +void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/) +{ + if (menu_filename.empty()) + { + return; + } + + llassert(LLMenuGL::sMenuContainer != NULL); + LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + LL_WARNS() << "Error loading menu_button menu" << LL_ENDL; + return; + } + + setMenu(menu, position, true); +} + +void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/) +{ + if (!menu) return; + + cleanup(); // destroy the previous memnu if we own it + + mMenuHandle = menu->getHandle(); + mMenuPosition = position; + mOwnMenu = take_ownership; + + menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); +} + +bool LLMenuButton::handleKeyHere(KEY key, MASK mask ) +{ + if (!getMenu()) 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 + // menu emerging event before actually displaying the menu. See STORM-263. + LLUICtrl::handleMouseDown(-1, -1, MASK_NONE); + + toggleMenu(); + return true; + } + + LLToggleableMenu* menu = getMenu(); + if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE) + { + menu->setVisible(false); + return true; + } + + return false; +} + +bool LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) +{ + LLButton::handleMouseDown(x, y, mask); + + toggleMenu(); + + return true; +} + +void LLMenuButton::toggleMenu() +{ + if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) + { + return; + } + + LLToggleableMenu* menu = getMenu(); + if (!menu) return; + + // 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) + { + setForcePressedState(false); + mIsMenuShown = false; + } + else + { + menu->buildDrawLabels(); + menu->arrangeAndClear(); + menu->updateParent(LLMenuGL::sMenuContainer); + + updateMenuOrigin(); + + LLMenuGL::showPopup(getParent(), menu, mX, mY); + + setForcePressedState(true); + mIsMenuShown = true; + } +} + +void LLMenuButton::updateMenuOrigin() +{ + LLToggleableMenu* menu = getMenu(); + if (!menu) return; + + LLRect rect = getRect(); + + switch (mMenuPosition) + { + case MP_TOP_LEFT: + { + mX = rect.mLeft; + mY = rect.mTop + menu->getRect().getHeight(); + break; + } + case MP_TOP_RIGHT: + { + const LLRect& menu_rect = menu->getRect(); + mX = rect.mRight - menu_rect.getWidth(); + mY = rect.mTop + menu_rect.getHeight(); + break; + } + case MP_BOTTOM_LEFT: + { + mX = rect.mLeft; + mY = rect.mBottom; + break; + } + case MP_BOTTOM_RIGHT: + { + const LLRect& menu_rect = menu->getRect(); + mX = rect.mRight - menu_rect.getWidth(); + mY = rect.mBottom; + break; + } + } +} + +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; + } +} + +void LLMenuButton::cleanup() +{ + if (mMenuHandle.get() && mOwnMenu) + { + mMenuHandle.get()->die(); + } +} |