PageRenderTime 52ms CodeModel.GetById 9ms app.highlight 38ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llui/llmenubutton.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 213 lines | 142 code | 39 blank | 32 comment | 26 complexity | a86fbb8787b8c2e23c3a7b3cdfbc1dd4 MD5 | raw file
  1/** 
  2 * @file llbutton.cpp
  3 * @brief LLButton base class
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "llmenubutton.h"
 30
 31// Linden library includes
 32#include "lltoggleablemenu.h"
 33#include "llstring.h"
 34#include "v4color.h"
 35
 36static LLDefaultChildRegistry::Register<LLMenuButton> r("menu_button");
 37
 38void LLMenuButton::MenuPositions::declareValues()
 39{
 40	declare("topleft", MP_TOP_LEFT);
 41	declare("topright", MP_TOP_RIGHT);
 42	declare("bottomleft", MP_BOTTOM_LEFT);
 43}
 44
 45LLMenuButton::Params::Params()
 46:	menu_filename("menu_filename"),
 47	position("position", MP_BOTTOM_LEFT)
 48{
 49}
 50
 51
 52LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
 53:	LLButton(p),
 54	mIsMenuShown(false),
 55	mMenuPosition(p.position)
 56{
 57	std::string menu_filename = p.menu_filename;
 58
 59	if (!menu_filename.empty())
 60	{
 61		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
 62		if (!menu)
 63		{
 64			llwarns << "Error loading menu_button menu" << llendl;
 65			return;
 66		}
 67
 68		menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
 69
 70		mMenuHandle = menu->getHandle();
 71
 72		updateMenuOrigin();
 73	}
 74}
 75
 76boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
 77{
 78	return LLUICtrl::setMouseDownCallback(cb);
 79}
 80
 81void LLMenuButton::hideMenu()
 82{
 83	if(mMenuHandle.isDead()) return;
 84
 85	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
 86	if (menu)
 87	{
 88		menu->setVisible(FALSE);
 89	}
 90}
 91
 92LLToggleableMenu* LLMenuButton::getMenu()
 93{
 94	return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
 95}
 96
 97void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/)
 98{
 99	if (!menu) return;
100
101	mMenuHandle = menu->getHandle();
102	mMenuPosition = position;
103
104	menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
105}
106
107BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
108{
109	if (mMenuHandle.isDead()) return FALSE;
110
111	if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
112	{
113		// *HACK: We emit the mouse down signal to fire the callback bound to the
114		// menu emerging event before actually displaying the menu. See STORM-263.
115		LLUICtrl::handleMouseDown(-1, -1, MASK_NONE);
116
117		toggleMenu();
118		return TRUE;
119	}
120
121	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
122	if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
123	{
124		menu->setVisible(FALSE);
125		return TRUE;
126	}
127	
128	return FALSE;
129}
130
131BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
132{
133	LLButton::handleMouseDown(x, y, mask);
134
135	toggleMenu();
136	
137	return TRUE;
138}
139
140void LLMenuButton::toggleMenu()
141{
142	if(mMenuHandle.isDead()) return;
143
144	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
145	if (!menu) return;
146
147	// Store the button rectangle to toggle menu visibility if a mouse event
148	// occurred inside or outside the button rect.
149	menu->setButtonRect(this);
150
151	if (!menu->toggleVisibility() && mIsMenuShown)
152	{
153		setForcePressedState(false);
154		mIsMenuShown = false;
155	}
156	else
157	{
158		menu->buildDrawLabels();
159		menu->arrangeAndClear();
160		menu->updateParent(LLMenuGL::sMenuContainer);
161
162		updateMenuOrigin();
163
164		LLMenuGL::showPopup(getParent(), menu, mX, mY);
165
166		setForcePressedState(true);
167		mIsMenuShown = true;
168	}
169}
170
171void LLMenuButton::updateMenuOrigin()
172{
173	if (mMenuHandle.isDead()) return;
174
175	LLRect rect = getRect();
176
177	switch (mMenuPosition)
178	{
179		case MP_TOP_LEFT:
180		{
181			mX = rect.mLeft;
182			mY = rect.mTop + mMenuHandle.get()->getRect().getHeight();
183			break;
184		}
185		case MP_TOP_RIGHT:
186		{
187			const LLRect& menu_rect = mMenuHandle.get()->getRect();
188			mX = rect.mRight - menu_rect.getWidth();
189			mY = rect.mTop + menu_rect.getHeight();
190			break;
191		}
192		case MP_BOTTOM_LEFT:
193		{
194			mX = rect.mLeft;
195			mY = rect.mBottom;
196			break;
197		}
198	}
199}
200
201void LLMenuButton::onMenuVisibilityChange(const LLSD& param)
202{
203	bool new_visibility = param["visibility"].asBoolean();
204	bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean();
205
206	// Reset the button "pressed" state only if the menu is shown by this particular
207	// menu button (not any other control) and is not being closed by a click on the button.
208	if (!new_visibility && !is_closed_by_button_click && mIsMenuShown)
209	{
210		setForcePressedState(false);
211		mIsMenuShown = false;
212	}
213}