diff options
Diffstat (limited to 'indra/llui')
37 files changed, 1704 insertions, 241 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index b3b2f4ae56..dded8ab661 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -5,6 +5,7 @@ project(llui)  include(00-Common)  include(LLCommon)  include(LLImage) +include(LLInventory)  include(LLMath)  include(LLMessage)  include(LLRender) @@ -16,6 +17,7 @@ include(LLXUIXML)  include_directories(      ${LLCOMMON_INCLUDE_DIRS}      ${LLIMAGE_INCLUDE_DIRS} +    ${LLINVENTORY_INCLUDE_DIRS}      ${LLMATH_INCLUDE_DIRS}      ${LLMESSAGE_INCLUDE_DIRS}      ${LLRENDER_INCLUDE_DIRS} @@ -35,6 +37,7 @@ set(llui_SOURCE_FILES      llcheckboxctrl.cpp      llclipboard.cpp      llcombobox.cpp +    llcommandmanager.cpp      llconsole.cpp      llcontainerview.cpp      llctrlselectioninterface.cpp @@ -99,6 +102,7 @@ set(llui_SOURCE_FILES      lltimectrl.cpp      lltransutil.cpp      lltoggleablemenu.cpp +    lltoolbar.cpp      lltooltip.cpp      llui.cpp      lluicolortable.cpp @@ -131,6 +135,7 @@ set(llui_HEADER_FILES      llcheckboxctrl.h      llclipboard.h      llcombobox.h +    llcommandmanager.h      llconsole.h      llcontainerview.h      llctrlselectioninterface.h @@ -200,6 +205,7 @@ set(llui_HEADER_FILES      lltextvalidate.h      lltimectrl.h      lltoggleablemenu.h +    lltoolbar.h      lltooltip.h      lltransutil.h      lluicolortable.h @@ -245,6 +251,7 @@ target_link_libraries(llui      ${LLRENDER_LIBRARIES}      ${LLWINDOW_LIBRARIES}      ${LLIMAGE_LIBRARIES} +    ${LLINVENTORY_LIBRARIES}      ${LLVFS_LIBRARIES}    # ugh, just for LLDir      ${LLXUIXML_LIBRARIES}      ${LLXML_LIBRARIES} diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 2459429f6e..f259e8027e 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -314,7 +314,7 @@ boost::signals2::connection LLButton::setHeldDownCallback( const commit_signal_t  } -// *TODO: Deprecate (for backwards compatability only) +// *TODO: Deprecate (for backwards compatibility only)  boost::signals2::connection LLButton::setClickedCallback( button_callback_t cb, void* data )  {  	return setClickedCallback(boost::bind(cb, data)); @@ -554,6 +554,16 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)  	return TRUE;  } +void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height) +{ +	overlay_width = mImageOverlay->getWidth(); +	overlay_height = mImageOverlay->getHeight(); + +	F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f); +	overlay_width = llround((F32)overlay_width * scale_factor); +	overlay_height = llround((F32)overlay_height * scale_factor); +} +  // virtual  void LLButton::draw() @@ -781,12 +791,10 @@ void LLButton::draw()  	if (mImageOverlay.notNull())  	{  		// get max width and height (discard level 0) -		S32 overlay_width = mImageOverlay->getWidth(); -		S32 overlay_height = mImageOverlay->getHeight(); +		S32 overlay_width; +		S32 overlay_height; -		F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f); -		overlay_width = llround((F32)overlay_width * scale_factor); -		overlay_height = llround((F32)overlay_height * scale_factor); +		getOverlayImageSize(overlay_width, overlay_height);  		S32 center_x = getLocalRect().getCenterX();  		S32 center_y = getLocalRect().getCenterY(); @@ -811,6 +819,7 @@ void LLButton::draw()  		{  		case LLFontGL::LEFT:  			text_left += overlay_width + mImgOverlayLabelSpace; +			text_width -= overlay_width + mImgOverlayLabelSpace;  			mImageOverlay->draw(  				mLeftHPad,  				center_y - (overlay_height / 2),  @@ -828,6 +837,7 @@ void LLButton::draw()  			break;  		case LLFontGL::RIGHT:  			text_right -= overlay_width + mImgOverlayLabelSpace; +			text_width -= overlay_width + mImgOverlayLabelSpace;  			mImageOverlay->draw(  				getRect().getWidth() - mRightHPad - overlay_width,  				center_y - (overlay_height / 2),  @@ -919,7 +929,7 @@ void LLButton::setToggleState(BOOL b)  void LLButton::setFlashing( BOOL b )	  {  -	if (b != mFlashing) +	if ((bool)b != mFlashing)  	{  		mFlashing = b;   		mFlashingTimer.reset(); @@ -989,11 +999,32 @@ void LLButton::resize(LLUIString label)  	// get current btn length   	S32 btn_width =getRect().getWidth();      // check if it need resize  -	if (mAutoResize == TRUE) +	if (mAutoResize)  	{  -		if (btn_width - (mRightHPad + mLeftHPad) < label_width) +		S32 min_width = label_width + mLeftHPad + mRightHPad; +		if (mImageOverlay) +		{ +			S32 overlay_width = mImageOverlay->getWidth(); +			F32 scale_factor = getRect().getHeight() / (F32)mImageOverlay->getHeight(); +			overlay_width = llround((F32)overlay_width * scale_factor); + +			switch(mImageOverlayAlignment) +			{ +			case LLFontGL::LEFT: +			case LLFontGL::RIGHT: +				min_width += overlay_width + mImgOverlayLabelSpace; +				break; +			case LLFontGL::HCENTER: +				min_width = llmax(min_width, overlay_width + mLeftHPad + mRightHPad); +				break; +			default: +				// draw nothing +				break; +			} +		} +		if (btn_width < min_width)  		{ -			setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mLeft + label_width + mLeftHPad + mRightHPad , getRect().mBottom)); +			reshape(min_width, getRect().getHeight());  		}  	}   } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 5968916006..08b45e01b3 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -270,6 +270,7 @@ public:  protected:  	LLPointer<LLUIImage> getImageUnselected() const	{ return mImageUnselected; }  	LLPointer<LLUIImage> getImageSelected() const	{ return mImageSelected; } +	void getOverlayImageSize(S32& overlay_width, S32& overlay_height);  	LLFrameTimer	mMouseDownTimer; @@ -327,15 +328,14 @@ private:  	LLUIColor					mImageColor;  	LLUIColor					mDisabledImageColor; -	BOOL						mIsToggle; -	BOOL						mScaleImage; +	bool						mIsToggle; +	bool						mScaleImage; -	BOOL						mDropShadowedText; -	BOOL						mAutoResize; -	BOOL						mUseEllipses; -	BOOL						mBorderEnabled; - -	BOOL						mFlashing; +	bool						mDropShadowedText; +	bool						mAutoResize; +	bool						mUseEllipses; +	bool						mBorderEnabled; +	bool						mFlashing;  	LLFontGL::HAlign			mHAlign;  	S32							mLeftHPad; @@ -355,9 +355,9 @@ private:  	F32							mHoverGlowStrength;  	F32							mCurGlowStrength; -	BOOL						mNeedsHighlight; -	BOOL						mCommitOnReturn; -	BOOL						mFadeWhenDisabled; +	bool						mNeedsHighlight; +	bool						mCommitOnReturn; +	bool						mFadeWhenDisabled;  	bool						mForcePressedState;  	LLFrameTimer				mFlashingTimer; diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp index 984c4ec5fb..6910b962a1 100644 --- a/indra/llui/llclipboard.cpp +++ b/indra/llui/llclipboard.cpp @@ -40,6 +40,7 @@ LLClipboard gClipboard;  LLClipboard::LLClipboard()  { +	mSourceItem = NULL;  } @@ -134,3 +135,8 @@ BOOL LLClipboard::canPastePrimaryString() const  {  	return LLView::getWindow()->isPrimaryTextAvailable();  } + +void LLClipboard::setSourceObject(const LLUUID& source_id, LLAssetType::EType type)  +{ +	mSourceItem = new LLInventoryObject (source_id, LLUUID::null, type, ""); +} diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index 24cb46c3f4..9371b94284 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -30,6 +30,8 @@  #include "llstring.h"  #include "lluuid.h" +#include "stdenums.h" +#include "llinventory.h"  class LLClipboard @@ -52,9 +54,14 @@ public:  	BOOL		canPastePrimaryString() const;  	const LLWString&	getPastePrimaryWString(LLUUID* source_id = NULL);	 +	// Support clipboard for object known only by their uuid and asset type +	void		  setSourceObject(const LLUUID& source_id, LLAssetType::EType type); +	const LLInventoryObject* getSourceObject() { return mSourceItem; } +	  private: -	LLUUID		mSourceID; +	LLUUID      mSourceID;  	LLWString	mString; +	LLInventoryObject* mSourceItem;  }; diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp new file mode 100644 index 0000000000..2bd50af7af --- /dev/null +++ b/indra/llui/llcommandmanager.cpp @@ -0,0 +1,182 @@ +/**  + * @file llcommandmanager.cpp + * @brief LLCommandManager class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +// A control that displays the name of the chosen item, which when +// clicked shows a scrolling box of options. + +#include "linden_common.h" + +#include "llcommandmanager.h" +#include "lldir.h" +#include "llerror.h" +#include "llxuiparser.h" + +#include <boost/foreach.hpp> + + +// +// LLCommandId class +// + +const LLCommandId LLCommandId::null("null command"); + +// +// LLCommand class +// + +LLCommand::Params::Params() +	: available_in_toybox("available_in_toybox", false) +	, icon("icon") +	, label_ref("label_ref") +	, name("name") +	, tooltip_ref("tooltip_ref") +	, execute_function("execute_function") +	, execute_parameters("execute_parameters") +	, is_enabled_function("is_enabled_function") +	, is_enabled_parameters("is_enabled_parameters") +	, is_running_function("is_running_function") +	, is_running_parameters("is_running_parameters") +	, is_starting_function("is_starting_function") +	, is_starting_parameters("is_starting_parameters") +{ +} + +LLCommand::LLCommand(const LLCommand::Params& p) +	: mAvailableInToybox(p.available_in_toybox) +	, mIcon(p.icon) +	, mIdentifier(p.name) +	, mLabelRef(p.label_ref) +	, mTooltipRef(p.tooltip_ref) +	, mExecuteFunction(p.execute_function) +	, mExecuteParameters(p.execute_parameters) +	, mIsEnabledFunction(p.is_enabled_function) +	, mIsEnabledParameters(p.is_enabled_parameters) +	, mIsRunningFunction(p.is_running_function) +	, mIsRunningParameters(p.is_running_parameters) +	, mIsStartingFunction(p.is_starting_function) +	, mIsStartingParameters(p.is_starting_parameters) +{ +} + + +// +// LLCommandManager class +// + +LLCommandManager::LLCommandManager() +{ +} + +LLCommandManager::~LLCommandManager() +{ +	for (CommandVector::iterator cmdIt = mCommands.begin(); cmdIt != mCommands.end(); ++cmdIt) +	{ +		LLCommand * command = *cmdIt; + +		delete command; +	} +} + +U32 LLCommandManager::commandCount() const +{ +	return mCommands.size(); +} + +LLCommand * LLCommandManager::getCommand(U32 commandIndex) +{ +	return mCommands[commandIndex]; +} + +LLCommand * LLCommandManager::getCommand(const LLCommandId& commandId) +{ +	LLCommand * command_match = NULL; + +	CommandIndexMap::const_iterator found = mCommandIndices.find(commandId); +	 +	if (found != mCommandIndices.end()) +	{ +		command_match = mCommands[found->second]; +	} + +	return command_match; +} + +LLCommand * LLCommandManager::getCommand(const LLUUID& commandUUID) +{ +	LLCommand * command_match = NULL; +	 +	CommandUUIDMap::const_iterator found = mCommandUUIDs.find(commandUUID); +	 +	if (found != mCommandUUIDs.end()) +	{ +		command_match = mCommands[found->second]; +	} +	 +	return command_match; +} + +void LLCommandManager::addCommand(LLCommand * command) +{ +	LLCommandId command_id = command->id(); +	mCommandIndices[command_id] = mCommands.size(); +	mCommandUUIDs[command_id.uuid()] = mCommands.size(); +	mCommands.push_back(command); + +	lldebugs << "Successfully added command: " << command->id().name() << llendl; +} + +//static +bool LLCommandManager::load() +{ +	LLCommandManager& mgr = LLCommandManager::instance(); + +	std::string commands_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "commands.xml"); + +	LLCommandManager::Params commandsParams; + +	LLSimpleXUIParser parser; +	 +	if (!parser.readXUI(commands_file, commandsParams)) +	{ +		llerrs << "Unable to load xml file: " << commands_file << llendl; +		return false; +	} + +	if (!commandsParams.validateBlock()) +	{ +		llerrs << "Unable to validate commands param block from file: " << commands_file << llendl; +		return false; +	} + +	BOOST_FOREACH(LLCommand::Params& commandParams, commandsParams.commands) +	{ +		LLCommand * command = new LLCommand(commandParams); + +		mgr.addCommand(command); +	} + +	return true; +} diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h new file mode 100644 index 0000000000..b11f905574 --- /dev/null +++ b/indra/llui/llcommandmanager.h @@ -0,0 +1,199 @@ +/**  + * @file llcommandmanager.h + * @brief LLCommandManager class to hold commands + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +#ifndef LL_LLCOMMANDMANAGER_H +#define LL_LLCOMMANDMANAGER_H + +#include "llinitparam.h" +#include "llsingleton.h" + + +class LLCommand; +class LLCommandManager; + + +class LLCommandId +{ +public: +	friend class LLCommand; +	friend class LLCommandManager; + +	struct Params : public LLInitParam::Block<Params> +	{ +		Mandatory<std::string> name; + +		Params() +		:	name("name") +		{} +	}; + +	LLCommandId(const std::string& name) +		: mName(name) +	{ +		mUUID = LLUUID::LLUUID::generateNewID(name); +	} + +	LLCommandId(const Params& p) +	:	mName(p.name) +	{ +		mUUID = LLUUID::LLUUID::generateNewID(p.name); +	} + +	const std::string& name() const { return mName; } +	const LLUUID& uuid() const { return mUUID; } + +	bool operator!=(const LLCommandId& command) const +	{ +		return (mName != command.mName); +	} + +	bool operator==(const LLCommandId& command) const +	{ +		return (mName == command.mName); +	} + +	bool operator<(const LLCommandId& command) const +	{ +		return (mName < command.mName); +	} + +	static const LLCommandId null; + +private: +	std::string mName; +	LLUUID		mUUID; +}; + +typedef std::list<LLCommandId> command_id_list_t; + + +class LLCommand +{ +public: +	struct Params : public LLInitParam::Block<Params> +	{ +		Mandatory<bool>			available_in_toybox; +		Mandatory<std::string>	icon; +		Mandatory<std::string>	label_ref; +		Mandatory<std::string>	name; +		Mandatory<std::string>	tooltip_ref; + +		Mandatory<std::string>	execute_function; +		Optional<LLSD>			execute_parameters; + +		Optional<std::string>	is_enabled_function; +		Optional<LLSD>			is_enabled_parameters; + +		Optional<std::string>	is_running_function; +		Optional<LLSD>			is_running_parameters; + +		Optional<std::string>	is_starting_function; +		Optional<LLSD>			is_starting_parameters; + +		Params(); +	}; + +	LLCommand(const LLCommand::Params& p); + +	const bool availableInToybox() const { return mAvailableInToybox; } +	const std::string& icon() const { return mIcon; } +	const LLCommandId& id() const { return mIdentifier; } +	const std::string& labelRef() const { return mLabelRef; } +	const std::string& tooltipRef() const { return mTooltipRef; } + +	const std::string& executeFunctionName() const { return mExecuteFunction; } +	const LLSD& executeParameters() const { return mExecuteParameters; } + +	const std::string& isEnabledFunctionName() const { return mIsEnabledFunction; } +	const LLSD& isEnabledParameters() const { return mIsEnabledParameters; } + +	const std::string& isRunningFunctionName() const { return mIsRunningFunction; } +	const LLSD& isRunningParameters() const { return mIsRunningParameters; } + +	const std::string& isStartingFunctionName() const { return mIsStartingFunction; } +	const LLSD& isStartingParameters() const { return mIsStartingParameters; } + +private: +	LLCommandId mIdentifier; + +	bool        mAvailableInToybox; +	std::string mIcon; +	std::string mLabelRef; +	std::string mTooltipRef; + +	std::string mExecuteFunction; +	LLSD        mExecuteParameters; + +	std::string mIsEnabledFunction; +	LLSD        mIsEnabledParameters; + +	std::string mIsRunningFunction; +	LLSD        mIsRunningParameters; + +	std::string mIsStartingFunction; +	LLSD        mIsStartingParameters; +}; + + +class LLCommandManager +:	public LLSingleton<LLCommandManager> +{ +public: +	struct Params : public LLInitParam::Block<Params> +	{ +		Multiple< LLCommand::Params, AtLeast<1> > commands; + +		Params() +			:	commands("command") +		{ +		} +	}; + +	LLCommandManager(); +	~LLCommandManager(); + +	U32 commandCount() const; +	LLCommand * getCommand(U32 commandIndex); +	LLCommand * getCommand(const LLCommandId& commandId); +	LLCommand * getCommand(const LLUUID& commandUUID); + +	static bool load(); + +protected: +	void addCommand(LLCommand * command); + +private: +	typedef std::map<LLUUID, U32>	    CommandUUIDMap; +	typedef std::map<LLCommandId, U32>	CommandIndexMap; +	typedef std::vector<LLCommand *>	CommandVector; +	 +	CommandVector	mCommands; +	CommandIndexMap	mCommandIndices; +	CommandUUIDMap	mCommandUUIDs; +}; + + +#endif // LL_LLCOMMANDMANAGER_H diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index b1c27126d9..6e39fcd714 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -97,6 +97,7 @@ void LLDockControl::getAllowedRect(LLRect& rect)  void LLDockControl::repositionDockable()  { +	if (!mDockWidget) return;  	LLRect dockRect = mDockWidget->calcScreenRect();  	LLRect rootRect;  	mGetAllowedRectCallback(rootRect); @@ -160,7 +161,7 @@ bool LLDockControl::isDockVisible()  			case TOP:  			{  				// check is dock inside parent rect -				// assume that parent for all dockable flaoters +				// assume that parent for all dockable floaters  				// is the root view  				LLRect dockParentRect =  						mDockWidget->getRootView()->calcScreenRect(); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 58c2d34253..fba59e82e1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -293,7 +293,7 @@ public:  protected:  	virtual void    applySavedVariables(); -	void			applyRectControl(); +	virtual void	applyRectControl();  	void			applyDockState();  	void			storeRectControl();  	void			storeVisibilityControl(); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index fc7dcfcc4e..27e96856b3 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -453,6 +453,47 @@ void LLFloaterReg::toggleFloaterInstance(const LLSD& sdname)  }  //static +void LLFloaterReg::toggleToolbarFloaterInstance(const LLSD& sdname) +{ +	// +	// Floaters controlled by the toolbar behave a bit differently from others. +	// Namely they have 3-4 states as defined in the design wiki page here: +	//   https://wiki.lindenlab.com/wiki/FUI_Button_states +	// +	// The basic idea is this: +	// * If the target floater is minimized, this button press will un-minimize it. +	// * Else if the target floater is closed open it. +	// * Else if the target floater does not have focus, give it focus. +	//       * Also, if it is not on top, bring it forward when focus is given. +	// * Else the target floater is open, close it. +	//  + +	// First parse the parameter +	LLSD key; +	std::string name = sdname.asString(); +	parse_name_key(name, key); + +	LLFloater* instance = findInstance(name, key);  + +	if (LLFloater::isMinimized(instance)) +	{ +		instance->setMinimized(FALSE); +	} +	else if (!LLFloater::isShown(instance)) +	{ +		showInstance(name, key, TRUE); +	} +	else if (!instance->hasFocus() && !instance->getIsChrome()) +	{ +		instance->setFocus(TRUE); +	} +	else +	{ +		instance->closeFloater(); +	} +} + +//static  bool LLFloaterReg::floaterInstanceVisible(const LLSD& sdname)  {  	LLSD key; diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index a2027a77a0..6239d98a7d 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -127,6 +127,7 @@ public:  	static void showFloaterInstance(const LLSD& sdname);  	static void hideFloaterInstance(const LLSD& sdname);  	static void toggleFloaterInstance(const LLSD& sdname); +	static void toggleToolbarFloaterInstance(const LLSD& sdname);  	static bool floaterInstanceVisible(const LLSD& sdname);  	static bool floaterInstanceMinimized(const LLSD& sdname); diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index a250404292..4991c4afa6 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -58,7 +58,9 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)  	mCollapsed(FALSE),  	mCollapseAmt(0.f),  	mVisibleAmt(1.f), // default to fully visible -	mResizeBar(NULL)  +	mResizeBar(NULL), +	mFractionalSize(0.f), +	mOrientation(LLLayoutStack::HORIZONTAL)  {  	// Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value  	if (p.expanded_min_dim.isProvided()) @@ -88,9 +90,22 @@ LLLayoutPanel::~LLLayoutPanel()  	mResizeBar = NULL;  } -F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation) +void LLLayoutPanel::reshape(S32 width, S32 height, BOOL called_from_parent)  { -	if (orientation == LLLayoutStack::HORIZONTAL) +	if (mOrientation == LLLayoutStack::HORIZONTAL) +	{ +		mFractionalSize += width - llround(mFractionalSize); +	} +	else +	{ +		mFractionalSize += height - llround(mFractionalSize); +	} +	LLPanel::reshape(width, height, called_from_parent); +} + +F32 LLLayoutPanel::getCollapseFactor() +{ +	if (mOrientation == LLLayoutStack::HORIZONTAL)  	{  		F32 collapse_amt =   			clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth())); @@ -149,11 +164,11 @@ void LLLayoutStack::draw()  		// scale clipping rectangle by visible amount  		if (mOrientation == HORIZONTAL)  		{ -			clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor(mOrientation)); +			clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());  		}  		else  		{ -			clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor(mOrientation)); +			clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());  		}  		LLPanel* panelp = (*panel_it); @@ -193,36 +208,15 @@ bool LLLayoutStack::addChild(LLView* child, S32 tab_group)  	LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);  	if (panelp)  	{ +		panelp->mFractionalSize = (mOrientation == HORIZONTAL) +									? panelp->getRect().getWidth() +									: panelp->getRect().getHeight(); +		panelp->setOrientation(mOrientation);  		mPanels.push_back(panelp);  	}  	return LLView::addChild(child, tab_group);  } - -S32 LLLayoutStack::getDefaultHeight(S32 cur_height) -{ -	// if we are spanning our children (crude upward propagation of size) -	// then don't enforce our size on our children -	if (mOrientation == HORIZONTAL) -	{ -		cur_height = llmax(mMinHeight, getRect().getHeight()); -	} - -	return cur_height; -} - -S32 LLLayoutStack::getDefaultWidth(S32 cur_width) -{ -	// if we are spanning our children (crude upward propagation of size) -	// then don't enforce our size on our children -	if (mOrientation == VERTICAL) -	{ -		cur_width = llmax(mMinWidth, getRect().getWidth()); -	} - -	return cur_width; -} -  void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front)  {  	LLLayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move); @@ -317,9 +311,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)  	createResizeBars();  	// calculate current extents -	S32 total_width = 0; -	S32 total_height = 0; +	F32 total_size = 0.f; +	// +	// animate visibility +	//  	e_panel_list_t::iterator panel_it;  	for (panel_it = mPanels.begin(); panel_it != mPanels.end();	++panel_it)  	{ @@ -361,179 +357,110 @@ void LLLayoutStack::updateLayout(BOOL force_resize)  			}  		} -		if (panelp->mCollapsed) -		{ -			panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); -		} -		else -		{ -			panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); -		} +		F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; +		panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); -		if (mOrientation == HORIZONTAL) -		{ -			// enforce minimize size constraint by default -			if (panelp->getRect().getWidth() < panelp->getRelevantMinDim()) -			{ -				panelp->reshape(panelp->getRelevantMinDim(), panelp->getRect().getHeight()); -			} -        	total_width += llround(panelp->getRect().getWidth() * panelp->getCollapseFactor(mOrientation)); -        	// want n-1 panel gaps for n panels -			if (panel_it != mPanels.begin()) -			{ -				total_width += mPanelSpacing; -			} -		} -		else //VERTICAL +        total_size += panelp->mFractionalSize * panelp->getCollapseFactor(); +        // want n-1 panel gaps for n panels +		if (panel_it != mPanels.begin())  		{ -			// enforce minimize size constraint by default -			if (panelp->getRect().getHeight() < panelp->getRelevantMinDim()) -			{ -				panelp->reshape(panelp->getRect().getWidth(), panelp->getRelevantMinDim()); -			} -			total_height += llround(panelp->getRect().getHeight() * panelp->getCollapseFactor(mOrientation)); -			if (panel_it != mPanels.begin()) -			{ -				total_height += mPanelSpacing; -			} +			total_size += mPanelSpacing;  		}  	}  	S32 num_resizable_panels = 0; -	S32 shrink_headroom_available = 0; -	S32 shrink_headroom_total = 0; +	F32 shrink_headroom_available = 0.f; +	F32 shrink_headroom_total = 0.f;  	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)  	{ +		LLLayoutPanel* panelp = (*panel_it); +  		// panels that are not fully visible do not count towards shrink headroom -		if ((*panel_it)->getCollapseFactor(mOrientation) < 1.f)  +		if (panelp->getCollapseFactor() < 1.f)   		{  			continue;  		} -		S32 relevant_dimension = (mOrientation == HORIZONTAL) ? (*panel_it)->getRect().getWidth() : (*panel_it)->getRect().getHeight(); -		S32 relevant_min = (*panel_it)->getRelevantMinDim(); +		F32 cur_size = panelp->mFractionalSize; +		F32 min_size = (F32)panelp->getRelevantMinDim();  		// if currently resizing a panel or the panel is flagged as not automatically resizing  		// only track total available headroom, but don't use it for automatic resize logic -		if ((*panel_it)->mResizeBar->hasMouseCapture()  -			|| (!(*panel_it)->mAutoResize  +		if (panelp->mResizeBar->hasMouseCapture()  +			|| (!panelp->mAutoResize   				&& !force_resize))  		{ -			shrink_headroom_total += relevant_dimension - relevant_min; +			shrink_headroom_total += cur_size - min_size;  		}  		else  		{  			num_resizable_panels++; -			shrink_headroom_available += relevant_dimension - relevant_min; -			shrink_headroom_total += relevant_dimension - relevant_min; +			shrink_headroom_available += cur_size - min_size; +			shrink_headroom_total += cur_size - min_size;  		}  	}  	// calculate how many pixels need to be distributed among layout panels  	// positive means panels need to grow, negative means shrink -	S32 pixels_to_distribute; -	if (mOrientation == HORIZONTAL) -	{ -		pixels_to_distribute = getRect().getWidth() - total_width; -	} -	else //VERTICAL -	{ -		pixels_to_distribute = getRect().getHeight() - total_height; -	} +	F32 pixels_to_distribute = (mOrientation == HORIZONTAL) +							? getRect().getWidth() - total_size +							: getRect().getHeight() - total_size;  	// now we distribute the pixels... -	S32 cur_x = 0; -	S32 cur_y = getRect().getHeight(); +	F32 cur_x = 0.f; +	F32 cur_y = (F32)getRect().getHeight();  	for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)  	{  		LLLayoutPanel* panelp = (*panel_it); -		S32 cur_width = panelp->getRect().getWidth(); -		S32 cur_height = panelp->getRect().getHeight(); -		S32 new_width = cur_width; -		S32 new_height = cur_height; -		S32 relevant_min = panelp->getRelevantMinDim(); - -		if (mOrientation == HORIZONTAL) -		{ -			new_width = llmax(relevant_min, new_width); -		} -		else -		{ -			new_height = llmax(relevant_min, new_height); -		} -		S32 delta_size = 0; +		F32 min_size = panelp->getRelevantMinDim(); +		F32 delta_size = 0.f;  		// if panel can automatically resize (not animating, and resize flag set)... -		if (panelp->getCollapseFactor(mOrientation) == 1.f  +		if (panelp->getCollapseFactor() == 1.f   			&& (force_resize || panelp->mAutoResize)   			&& !panelp->mResizeBar->hasMouseCapture())   		{ -			if (mOrientation == HORIZONTAL) +			if (pixels_to_distribute < 0.f)  			{ -				// if we're shrinking -				if (pixels_to_distribute < 0) -				{ -					// shrink proportionally to amount over minimum -					// so we can do this in one pass -					delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - relevant_min) / (F32)shrink_headroom_available)) : 0; -					shrink_headroom_available -= (cur_width - relevant_min); -				} -				else -				{ -					// grow all elements equally -					delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels); -					num_resizable_panels--; -				} -				pixels_to_distribute -= delta_size; -				new_width = llmax(relevant_min, cur_width + delta_size); +				// shrink proportionally to amount over minimum +				// so we can do this in one pass +				delta_size = (shrink_headroom_available > 0.f)  +					? pixels_to_distribute * ((F32)(panelp->mFractionalSize - min_size) / shrink_headroom_available)  +					: 0.f; +				shrink_headroom_available -= (panelp->mFractionalSize - min_size);  			}  			else  			{ -				new_width = getDefaultWidth(new_width); -			} - -			if (mOrientation == VERTICAL) -			{ -				if (pixels_to_distribute < 0) -				{ -					// shrink proportionally to amount over minimum -					// so we can do this in one pass -					delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - relevant_min) / (F32)shrink_headroom_available)) : 0; -					shrink_headroom_available -= (cur_height - relevant_min); -				} -				else -				{ -					delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels); -					num_resizable_panels--; -				} -				pixels_to_distribute -= delta_size; -				new_height = llmax(relevant_min, cur_height + delta_size); -			} -			else -			{ -				new_height = getDefaultHeight(new_height); -			} -		} -		else -		{ -			if (mOrientation == HORIZONTAL) -			{ -				new_height = getDefaultHeight(new_height); -			} -			else // VERTICAL -			{ -				new_width = getDefaultWidth(new_width); +				// grow all elements equally +				delta_size = pixels_to_distribute / (F32)num_resizable_panels; +				num_resizable_panels--;  			} +			 +			panelp->mFractionalSize = llmax(min_size, panelp->mFractionalSize + delta_size); +			pixels_to_distribute -= delta_size;  		}  		// adjust running headroom count based on new sizes  		shrink_headroom_total += delta_size;  		LLRect panel_rect; -		panel_rect.setLeftTopAndSize(cur_x, cur_y, new_width, new_height); +		if (mOrientation == HORIZONTAL) +		{ +			panel_rect.setLeftTopAndSize(llround(cur_x),  +										llround(cur_y),  +										llround(panelp->mFractionalSize),  +										getRect().getHeight()); +		} +		else +		{ +			panel_rect.setLeftTopAndSize(llround(cur_x),  +										llround(cur_y),  +										getRect().getWidth(),  +										llround(panelp->mFractionalSize)); +		}  		panelp->setShape(panel_rect);  		LLRect resize_bar_rect = panel_rect; @@ -549,13 +476,14 @@ void LLLayoutStack::updateLayout(BOOL force_resize)  		}  		(*panel_it)->mResizeBar->setRect(resize_bar_rect); +		F32 size = ((*panel_it)->mFractionalSize * (*panel_it)->getCollapseFactor()) + (F32)mPanelSpacing;  		if (mOrientation == HORIZONTAL)  		{ -			cur_x += llround(new_width * (*panel_it)->getCollapseFactor(mOrientation)) + mPanelSpacing; +			cur_x += size;  		}  		else //VERTICAL  		{ -			cur_y -= llround(new_height * (*panel_it)->getCollapseFactor(mOrientation)) + mPanelSpacing; +			cur_y -= size;  		}  	} @@ -570,13 +498,13 @@ void LLLayoutStack::updateLayout(BOOL force_resize)  		{  			(*panel_it)->mResizeBar->setResizeLimits(  				relevant_min,  -				relevant_min + shrink_headroom_total); +				relevant_min + llround(shrink_headroom_total));  		}  		else //VERTICAL  		{  			(*panel_it)->mResizeBar->setResizeLimits(  				relevant_min,  -				relevant_min + shrink_headroom_total); +				relevant_min + llround(shrink_headroom_total));  		}  		// toggle resize bars based on panel visibility, resizability, etc diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index d8ef0aeaca..5d79505fc3 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -126,8 +126,6 @@ protected:  private:  	void createResizeBars();  	void calcMinExtents(); -	S32 getDefaultHeight(S32 cur_height); -	S32 getDefaultWidth(S32 cur_width);  	const ELayoutOrientation mOrientation; @@ -181,6 +179,8 @@ public:  	void initFromParams(const Params& p); +	void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +  	S32 getMinDim() const { return mMinDim; }  	void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; } @@ -202,22 +202,26 @@ public:  		return min_dim;  	} +	void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; } +  protected:  	LLLayoutPanel(const Params& p); -	F32 getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation); +	F32 getCollapseFactor(); -	bool mExpandedMinDimSpecified; -	S32 mExpandedMinDim; +	bool	mExpandedMinDimSpecified; +	S32		mExpandedMinDim; -	S32 mMinDim; -	S32 mMaxDim; -	BOOL mAutoResize; -	BOOL mUserResize; -	BOOL mCollapsed; +	S32		mMinDim; +	S32		mMaxDim; +	bool	mAutoResize; +	bool	mUserResize; +	bool	mCollapsed; +	F32		mVisibleAmt; +	F32		mCollapseAmt; +	F32		mFractionalSize; +	LLLayoutStack::ELayoutOrientation mOrientation;  	class LLResizeBar* mResizeBar; -	F32 mVisibleAmt; -	F32 mCollapseAmt;  }; diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 583bde360a..2518dbe3c7 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -60,7 +60,7 @@ public:  	typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t; -	struct MaxLength : public LLInitParam::Choice<MaxLength> +	struct MaxLength : public LLInitParam::ChoiceBlock<MaxLength>  	{  		Alternative<S32> bytes, chars; diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index c4eec1835c..6ac38f5ad4 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -34,6 +34,7 @@  // Project includes  #include "lluictrlfactory.h"  #include "lluiimage.h" +#include "boost/foreach.hpp"  // registered in llui.cpp to avoid being left out by MS linker  //static LLDefaultChildRegistry::Register<LLLoadingIndicator> r("loading_indicator"); @@ -51,11 +52,9 @@ LLLoadingIndicator::LLLoadingIndicator(const Params& p)  void LLLoadingIndicator::initFromParams(const Params& p)  { -	for (LLInitParam::ParamIterator<LLUIImage*>::const_iterator it = p.images().image.begin(), end_it = p.images().image.end(); -		it != end_it; -		++it) +	BOOST_FOREACH(LLUIImage* image, p.images.image)  	{ -		mImages.push_back(it->getValue()); +		mImages.push_back(image);  	}  	// Start timer for switching images. diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index 7c44478848..c1f979c111 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -51,7 +51,7 @@ class LLLoadingIndicator  	LOG_CLASS(LLLoadingIndicator);  public: -	struct Images : public LLInitParam::Block<Images> +	struct Images : public LLInitParam::BatchBlock<Images>  	{  		Multiple<LLUIImage*>	image; @@ -63,7 +63,7 @@ public:  	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>  	{  		Optional<F32>			images_per_sec; -		Batch<Images>			images; +		Optional<Images>		images;  		Params()  		:	images_per_sec("images_per_sec", 1.0f), diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 6cac841cde..badba7a416 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -947,7 +947,7 @@ LLMenuItemBranchGL::LLMenuItemBranchGL(const LLMenuItemBranchGL::Params& p)  LLMenuItemBranchGL::~LLMenuItemBranchGL()  { -	LLView::deleteViewByHandle(mBranchHandle); +	delete mBranchHandle.get();  }  // virtual diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 0c4d4fc897..462d69be2e 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -201,7 +201,7 @@ public:  		FormInput();  	}; -	struct FormElement : public LLInitParam::Choice<FormElement> +	struct FormElement : public LLInitParam::ChoiceBlock<FormElement>  	{  		Alternative<FormButton> button;  		Alternative<FormInput>	input; @@ -312,7 +312,7 @@ public:  		Optional<LLNotificationContext*>		context;  		Optional<void*>							responder; -		struct Functor : public LLInitParam::Choice<Functor> +		struct Functor : public LLInitParam::ChoiceBlock<Functor>  		{  			Alternative<std::string>										name;  			Alternative<LLNotificationFunctorRegistry::ResponseFunctor>	function; diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index ab777d37a5..fb50c9c123 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -91,7 +91,7 @@ struct LLNotificationTemplate  		// <notification> <unique/> </notification>  		// as well as  		// <notification> <unique> <context></context> </unique>... -		Flag			dummy_val; +		Optional<LLInitParam::Flag>	dummy_val;  	public:  		Multiple<UniquenessContext>	contexts; @@ -147,7 +147,7 @@ struct LLNotificationTemplate  		{}  	}; -	struct FormRef : public LLInitParam::Choice<FormRef> +	struct FormRef : public LLInitParam::ChoiceBlock<FormRef>  	{  		Alternative<LLNotificationForm::Params>		form;  		Alternative<TemplateRef>					form_template; diff --git a/indra/llui/llnotificationvisibilityrule.h b/indra/llui/llnotificationvisibilityrule.h index 78bdec2a8f..78788a275c 100644 --- a/indra/llui/llnotificationvisibilityrule.h +++ b/indra/llui/llnotificationvisibilityrule.h @@ -59,7 +59,7 @@ struct LLNotificationVisibilityRule  		{}  	}; -	struct Rule : public LLInitParam::Choice<Rule> +	struct Rule : public LLInitParam::ChoiceBlock<Rule>  	{  		Alternative<Filter>		show;  		Alternative<Filter>		hide; diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 790025cb2d..ab1c87caff 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -96,9 +96,6 @@ public:  		Params();  	}; -	// valid children for LLPanel are stored in this registry -	typedef LLDefaultChildRegistry child_registry_t; -  protected:  	friend class LLUICtrlFactory;  	// RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8 diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index c3a51c36c9..942e84eeb6 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -55,6 +55,8 @@ LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p)  	mImage( NULL ),  	mMinWidth( p.min_width ),  	mMinHeight( p.min_height ), +	mMaxWidth(S32_MAX), +	mMaxHeight(S32_MAX),  	mCorner( p.corner )  {  	if( RIGHT_BOTTOM == mCorner) @@ -177,6 +179,11 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)  				new_width = mMinWidth;  				delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());  			} +			else if (new_width > mMaxWidth) +			{ +				new_width = mMaxWidth; +				delta_x = x_multiple * (mMaxWidth - orig_rect.getWidth()); +			}  			S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;  			if( new_height < mMinHeight ) @@ -184,6 +191,11 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)  				new_height = mMinHeight;  				delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());  			} +			else if (new_height > mMaxHeight) +			{ +				new_height = mMaxHeight; +				delta_y = y_multiple * (mMaxHeight - orig_rect.getHeight()); +			}  			switch( mCorner )  			{ diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h index 531eb1db61..5cfe3fb63c 100644 --- a/indra/llui/llresizehandle.h +++ b/indra/llui/llresizehandle.h @@ -56,6 +56,9 @@ public:  	void			setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; } +	void			setMaxWidth(S32 width) { mMaxWidth = width;} +	void			setMaxHeight(S32 height) { mMaxHeight = height;} +  private:  	BOOL			pointInHandle( S32 x, S32 y ); @@ -66,7 +69,9 @@ private:  	LLCoordGL		mLastMouseDir;  	LLPointer<LLUIImage>	mImage;  	S32				mMinWidth; +	S32				mMaxWidth;  	S32				mMinHeight; +	S32				mMaxHeight;  	const ECorner	mCorner;  }; diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index 12baea8e0c..b4d4a6d05e 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -95,7 +95,7 @@ public:  		Optional<ESortDirection, SortNames>	sort_direction;  		Optional<bool>						sort_ascending; -		struct Width : public LLInitParam::Choice<Width> +		struct Width : public LLInitParam::ChoiceBlock<Width>  		{  			Alternative<bool>	dynamic_width;  			Alternative<S32>		pixel_width; @@ -112,7 +112,7 @@ public:  		Optional<Width>						width;  		// either an image or label is used in column header -		struct Header : public LLInitParam::Choice<Header> +		struct Header : public LLInitParam::ChoiceBlock<Header>  		{  			Alternative<std::string>			label;  			Alternative<LLUIImage*>			image; diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 04919e6991..4b69360e33 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -45,7 +45,7 @@ LLParamSDParser::LLParamSDParser()  	if (sReadFuncs.empty())  	{ -		registerParserFuncs<LLInitParam::NoParamValue>(readNoValue, &LLParamSDParser::writeNoValue); +		registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);  		registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);  		registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);  		registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>); @@ -72,7 +72,7 @@ bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const voi  	return true;  } -bool LLParamSDParser::writeNoValue(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack) +bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)  {  	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);  	if (!sdparser.mWriteRootSD) return false; @@ -226,7 +226,7 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)  	return sd_to_write;  } -bool LLParamSDParser::readNoValue(Parser& parser, void* val_ptr) +bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)  {  	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);  	return self.mCurReadSD == &NO_VALUE_MARKER; diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h index f776c781b3..a371c28f68 100644 --- a/indra/llui/llsdparam.h +++ b/indra/llui/llsdparam.h @@ -63,9 +63,9 @@ private:  	LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack);  	static bool writeU32Param(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack); -	static bool writeNoValue(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack); +	static bool writeFlag(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack); -	static bool readNoValue(Parser& parser, void* val_ptr); +	static bool readFlag(Parser& parser, void* val_ptr);  	static bool readS32(Parser& parser, void* val_ptr);  	static bool readU32(Parser& parser, void* val_ptr);  	static bool readF32(Parser& parser, void* val_ptr); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 7d545a1ba6..384d9116fc 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -237,7 +237,7 @@ public:  	friend class LLNormalTextSegment;  	friend class LLUICtrlFactory; -	struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams> +	struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>  	{  		Alternative<F32>	multiple;  		Alternative<S32>	pixels; diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp new file mode 100644 index 0000000000..07beb147d7 --- /dev/null +++ b/indra/llui/lltoolbar.cpp @@ -0,0 +1,682 @@ +/**  + * @file lltoolbar.cpp + * @author Richard Nelson + * @brief User customizable toolbar class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 <boost/foreach.hpp> +#include "lltoolbar.h" + +#include "llcommandmanager.h" +#include "llmenugl.h" +#include "lltrans.h" + +// uncomment this and remove the one in llui.cpp when there is an external reference to this translation unit +// thanks, MSVC! +//static LLDefaultChildRegistry::Register<LLToolBar> r1("toolbar"); + +namespace LLToolBarEnums +{ +	LLLayoutStack::ELayoutOrientation getOrientation(SideType sideType) +	{ +		LLLayoutStack::ELayoutOrientation orientation = LLLayoutStack::HORIZONTAL; + +		if ((sideType == SIDE_LEFT) || (sideType == SIDE_RIGHT)) +		{ +			orientation = LLLayoutStack::VERTICAL; +		} + +		return orientation; +	} +} + +using namespace LLToolBarEnums; + + +namespace LLInitParam +{ +	void TypeValues<ButtonType>::declareValues() +	{ +		declare("icons_with_text",	BTNTYPE_ICONS_WITH_TEXT); +		declare("icons_only",		BTNTYPE_ICONS_ONLY); +	} + +	void TypeValues<SideType>::declareValues() +	{ +		declare("bottom",	SIDE_BOTTOM); +		declare("left",		SIDE_LEFT); +		declare("right",	SIDE_RIGHT); +		declare("top",		SIDE_TOP); +	} +} + +LLToolBar::Params::Params() +:	button_display_mode("button_display_mode"), +	commands("command"), +	side("side", SIDE_TOP), +	button_icon("button_icon"), +	button_icon_and_text("button_icon_and_text"), +	read_only("read_only", false), +	wrap("wrap", true), +	pad_left("pad_left"), +	pad_top("pad_top"), +	pad_right("pad_right"), +	pad_bottom("pad_bottom"), +	pad_between("pad_between"), +	button_panel("button_panel") +{} + +LLToolBar::LLToolBar(const LLToolBar::Params& p) +:	LLUICtrl(p), +	mReadOnly(p.read_only), +	mButtonType(p.button_display_mode), +	mSideType(p.side), +	mWrap(p.wrap), +	mNeedsLayout(false), +	mButtonPanel(NULL), +	mCenteringStack(NULL), +	mPadLeft(p.pad_left), +	mPadRight(p.pad_right), +	mPadTop(p.pad_top), +	mPadBottom(p.pad_bottom), +	mPadBetween(p.pad_between), +	mPopupMenuHandle() +{ +	mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_WITH_TEXT] = p.button_icon_and_text; +	mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_ONLY] = p.button_icon; +} + +LLToolBar::~LLToolBar() +{ +	delete mPopupMenuHandle.get(); +} + +void LLToolBar::createContextMenu() +{ +	if (!mPopupMenuHandle.get()) +	{ +		// Setup bindings specific to this instance for the context menu options + +		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit_reg; +		commit_reg.add("Toolbars.EnableSetting", boost::bind(&LLToolBar::onSettingEnable, this, _2)); + +		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_reg; +		enable_reg.add("Toolbars.CheckSetting", boost::bind(&LLToolBar::isSettingChecked, this, _2)); + +		// Create the context menu +		LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_toolbars.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + +		if (menu) +		{ +			menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + +			mPopupMenuHandle = menu->getHandle(); +		} +		else +		{ +			llwarns << "Unable to load toolbars context menu." << llendl; +		} +	} +} + +void LLToolBar::initFromParams(const LLToolBar::Params& p) +{ +	// Initialize the base object +	LLUICtrl::initFromParams(p); +	 +	LLLayoutStack::ELayoutOrientation orientation = getOrientation(p.side); + +	LLLayoutStack::Params centering_stack_p; +	centering_stack_p.name = "centering_stack"; +	centering_stack_p.rect = getLocalRect(); +	centering_stack_p.follows.flags = FOLLOWS_ALL; +	centering_stack_p.orientation = orientation; +	centering_stack_p.mouse_opaque = false; + +	mCenteringStack = LLUICtrlFactory::create<LLLayoutStack>(centering_stack_p); +	addChild(mCenteringStack); +	 +	LLLayoutPanel::Params border_panel_p; +	border_panel_p.name = "border_panel"; +	border_panel_p.rect = getLocalRect(); +	border_panel_p.auto_resize = true; +	border_panel_p.user_resize = false; +	border_panel_p.mouse_opaque = false; +	 +	mCenteringStack->addChild(LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p)); + +	LLLayoutPanel::Params center_panel_p; +	center_panel_p.name = "center_panel"; +	center_panel_p.rect = getLocalRect(); +	center_panel_p.auto_resize = false; +	center_panel_p.user_resize = false; +	LLLayoutPanel* center_panel = LLUICtrlFactory::create<LLLayoutPanel>(center_panel_p); +	mCenteringStack->addChild(center_panel); + +	LLPanel::Params button_panel_p(p.button_panel); +	button_panel_p.rect = center_panel->getLocalRect(); +		button_panel_p.follows.flags = FOLLOWS_BOTTOM|FOLLOWS_LEFT; +	mButtonPanel = LLUICtrlFactory::create<LLPanel>(button_panel_p); +	center_panel->addChild(mButtonPanel); +	 +	mCenteringStack->addChild(LLUICtrlFactory::create<LLLayoutPanel>(border_panel_p)); + +	BOOST_FOREACH(LLCommandId::Params params, p.commands) +	{ +		addCommand(params); +	} + +	mNeedsLayout = true; +} + +bool LLToolBar::addCommand(const LLCommandId& commandId, int rank) +{ +	LLCommand * command = LLCommandManager::instance().getCommand(commandId); +	if (!command) return false; + +	// Create the button and do the things that don't need ordering +	LLToolBarButton* button = createButton(commandId); +	mButtonPanel->addChild(button); +	mButtonMap.insert(std::make_pair(commandId, button)); + +	// Insert the command and button in the right place in their respective lists +	if ((rank >= mButtonCommands.size()) || (rank < 0)) +	{ +		// In that case, back load +		mButtonCommands.push_back(commandId); +		mButtons.push_back(button); +	} +	else  +	{ +		// Insert in place: iterate to the right spot... +		std::list<LLToolBarButton*>::iterator it_button = mButtons.begin(); +		command_id_list_t::iterator it_command = mButtonCommands.begin(); +		while (rank > 0) +		{ +			++it_button; +			++it_command; +			rank--; +		} +		// ...then insert +		mButtonCommands.insert(it_command,commandId); +		mButtons.insert(it_button,button); +	} + +	mNeedsLayout = true; + +	return true; +} + +bool LLToolBar::removeCommand(const LLCommandId& commandId) +{ +	if (!hasCommand(commandId)) return false; +	 +	// First erase the map record +	command_id_map::iterator it = mButtonMap.find(commandId); +	mButtonMap.erase(it); +	 +	// Now iterate on the commands and buttons to identify the relevant records +	std::list<LLToolBarButton*>::iterator it_button = mButtons.begin(); +	command_id_list_t::iterator it_command = mButtonCommands.begin(); +	while (*it_command != commandId) +	{ +		++it_button; +		++it_command; +	} +	 +	// Delete the button and erase the command and button records +	delete (*it_button); +	mButtonCommands.erase(it_command); +	mButtons.erase(it_button); + +	mNeedsLayout = true; +	 +	return true; +} + +void LLToolBar::clearCommandsList() +{ +	// Clears the commands list +	mButtonCommands.clear(); +	// This will clear the buttons +	createButtons(); +} + +bool LLToolBar::hasCommand(const LLCommandId& commandId) const +{ +	if (commandId != LLCommandId::null) +	{ +		command_id_map::const_iterator it = mButtonMap.find(commandId); +		return (it != mButtonMap.end()); +	} + +	return false; +} + +bool LLToolBar::enableCommand(const LLCommandId& commandId, bool enabled) +{ +	LLButton * command_button = NULL; +	 +	if (commandId != LLCommandId::null) +	{ +		command_id_map::iterator it = mButtonMap.find(commandId); +		if (it != mButtonMap.end()) +		{ +			it->second->setEnabled(enabled); +		} +	} + +	return (command_button != NULL); +} + +BOOL LLToolBar::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	LLRect button_panel_rect; +	mButtonPanel->localRectToOtherView(mButtonPanel->getLocalRect(), &button_panel_rect, this); +	BOOL handle_it_here = !mReadOnly && button_panel_rect.pointInRect(x, y); + +	if (handle_it_here) +	{ +		createContextMenu(); + +		LLContextMenu * menu = (LLContextMenu *) mPopupMenuHandle.get(); + +		if (menu) +		{ +			menu->show(x, y); + +			LLMenuGL::showPopup(this, menu, x, y); +		} +	} + +	return handle_it_here; +} + +BOOL LLToolBar::isSettingChecked(const LLSD& userdata) +{ +	BOOL retval = FALSE; + +	const std::string setting_name = userdata.asString(); + +	if (setting_name == "icons_with_text") +	{ +		retval = (mButtonType == BTNTYPE_ICONS_WITH_TEXT); +	} +	else if (setting_name == "icons_only") +	{ +		retval = (mButtonType == BTNTYPE_ICONS_ONLY); +	} + +	return retval; +} + +void LLToolBar::onSettingEnable(const LLSD& userdata) +{ +	llassert(!mReadOnly); + +	const std::string setting_name = userdata.asString(); + +	if (setting_name == "icons_with_text") +	{ +		setButtonType(BTNTYPE_ICONS_WITH_TEXT); +	} +	else if (setting_name == "icons_only") +	{ +		setButtonType(BTNTYPE_ICONS_ONLY); +	} +} + +void LLToolBar::setButtonType(LLToolBarEnums::ButtonType button_type) +{ +	bool regenerate_buttons = (mButtonType != button_type); +	 +	mButtonType = button_type; + +	if (regenerate_buttons) +	{ +		createButtons(); +	} +} + +void LLToolBar::resizeButtonsInRow(std::vector<LLToolBarButton*>& buttons_in_row, S32 max_row_girth) +{ +	// make buttons in current row all same girth +	BOOST_FOREACH(LLToolBarButton* button, buttons_in_row) +	{ +		if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL) +		{ +			button->reshape(button->mWidthRange.clamp(button->getRect().getWidth()), max_row_girth); +		} +		else // VERTICAL +		{ +			button->reshape(max_row_girth, button->getRect().getHeight()); +		} +	} +} + +int LLToolBar::getRankFromPosition(S32 x, S32 y) +{ +	int rank = 0; + +	LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType); + +	// Simply compare the passed coord with the buttons outbound box +	std::list<LLToolBarButton*>::iterator it_button = mButtons.begin(); +	std::list<LLToolBarButton*>::iterator end_button = mButtons.end(); +	while (it_button != end_button) +	{ +		LLRect button_rect = (*it_button)->getRect(); +		if (((orientation == LLLayoutStack::HORIZONTAL) && (button_rect.mRight > x)) || +			((orientation == LLLayoutStack::VERTICAL)   && (button_rect.mTop   > y))    ) +		{ +			llinfos << "Merov debug : rank compute: orientation = " << orientation << ", x = " << x << ", y = " << y << llendl; +			llinfos << "Merov debug : rank compute: rect = " << button_rect.mLeft << ", " << button_rect.mTop << ", " << button_rect.mRight << ", " << button_rect.mBottom << llendl; +			break; +		} +		rank++; +		++it_button; +	} +	llinfos << "Merov debug : rank = " << rank << llendl; + +	return rank; +} + +void LLToolBar::updateLayoutAsNeeded() +{ +	if (!mNeedsLayout) return; + +	LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType); +	 +	// our terminology for orientation-agnostic layout is such that +	// length refers to a distance in the direction we stack the buttons  +	// and girth refers to a distance in the direction buttons wrap +	S32 max_row_girth = 0; +	S32 max_row_length = 0; + +	S32 max_length; +	S32 max_total_girth; +	S32 cur_start; +	S32 cur_row ; +	S32 row_pad_start; +	S32 row_pad_end; +	S32 girth_pad_end; +	S32 row_running_length; + +	if (orientation == LLLayoutStack::HORIZONTAL) +	{ +		max_length = getRect().getWidth() - mPadLeft - mPadRight; +		max_total_girth = getRect().getHeight() - mPadTop - mPadBottom; +		row_pad_start = mPadLeft; +		row_pad_end = mPadRight; +		cur_row = mPadTop; +		girth_pad_end = mPadBottom; +	} +	else // VERTICAL +	{ +		max_length = getRect().getHeight() - mPadTop - mPadBottom; +		max_total_girth = getRect().getWidth() - mPadLeft - mPadRight; +		row_pad_start = mPadTop; +		row_pad_end = mPadBottom; +		cur_row = mPadLeft; +		girth_pad_end = mPadRight; +	} +	 +	row_running_length = row_pad_start; +	cur_start = row_pad_start; + + +	LLRect panel_rect = mButtonPanel->getLocalRect(); + +	std::vector<LLToolBarButton*> buttons_in_row; + +	BOOST_FOREACH(LLToolBarButton* button, mButtons) +	{ +		button->reshape(button->mWidthRange.getMin(), button->mDesiredHeight); +		button->autoResize(); + +		S32 button_clamped_width = button->mWidthRange.clamp(button->getRect().getWidth()); +		S32 button_length = (orientation == LLLayoutStack::HORIZONTAL) +							? button_clamped_width +							: button->getRect().getHeight(); +		S32 button_girth = (orientation == LLLayoutStack::HORIZONTAL) +							? button->getRect().getHeight() +							: button_clamped_width; +		 +		// wrap if needed +		if (mWrap +			&& row_running_length + button_length > max_length	// out of room... +			&& cur_start != row_pad_start)						// ...and not first button in row +		{ +			if (orientation == LLLayoutStack::VERTICAL) +			{	// row girth (width in this case) is clamped to allowable button widths +				max_row_girth = button->mWidthRange.clamp(max_row_girth); +			} + +			// make buttons in current row all same girth +			resizeButtonsInRow(buttons_in_row, max_row_girth); +			buttons_in_row.clear(); + +			max_row_length = llmax(max_row_length, row_running_length); +			row_running_length = row_pad_start; +			cur_start = row_pad_start; +			cur_row += max_row_girth + mPadBetween; +			max_row_girth = 0; +		} + +		LLRect button_rect; +		if (orientation == LLLayoutStack::HORIZONTAL) +		{ +			button_rect.setLeftTopAndSize(cur_start, panel_rect.mTop - cur_row, button_clamped_width, button->getRect().getHeight()); +		} +		else // VERTICAL +		{ +			button_rect.setLeftTopAndSize(cur_row, panel_rect.mTop - cur_start, button_clamped_width, button->getRect().getHeight()); +		} +		button->setShape(button_rect); + +		buttons_in_row.push_back(button); + +		row_running_length += button_length + mPadBetween; +		cur_start = row_running_length; +		max_row_girth = llmax(button_girth, max_row_girth); +	} + +	// final resizing in "girth" direction +	S32 total_girth =	cur_row				// current row position... +						+ max_row_girth		// ...incremented by size of final row... +						+ girth_pad_end;	// ...plus padding reserved on end +	max_row_length = llmax(max_row_length, row_running_length - mPadBetween + row_pad_end); + +	resizeButtonsInRow(buttons_in_row, max_row_girth); + +	// grow and optionally shift toolbar to accommodate buttons +	if (orientation == LLLayoutStack::HORIZONTAL) +	{ +		if (mSideType == SIDE_TOP) +		{ // shift down to maintain top edge +			translate(0, getRect().getHeight() - total_girth); +		} + +		reshape(getRect().getWidth(), total_girth); +		mButtonPanel->reshape(max_row_length, total_girth); +	} +	else // VERTICAL +	{ +		if (mSideType == SIDE_RIGHT) +		{ // shift left to maintain right edge +			translate(getRect().getWidth() - total_girth, 0); +		} +		 +		reshape(total_girth, getRect().getHeight()); +		mButtonPanel->reshape(total_girth, max_row_length); +	} + +	// make parent fit button panel +	mButtonPanel->getParent()->setShape(mButtonPanel->getLocalRect()); + +	// re-center toolbar buttons +	mCenteringStack->updateLayout(); + +	// don't clear flag until after we've resized ourselves, to avoid laying out every frame +	mNeedsLayout = false; +} + + +void LLToolBar::draw() +{ +	if (mButtons.empty()) return; +	updateLayoutAsNeeded(); +	// rect may have shifted during layout +	LLUI::popMatrix(); +	LLUI::pushMatrix(); +	LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom, 0.f); + +	LLUICtrl::draw(); +} + +void LLToolBar::reshape(S32 width, S32 height, BOOL called_from_parent) +{ +	LLUICtrl::reshape(width, height, called_from_parent); +	mNeedsLayout = true; +} + +void LLToolBar::createButtons() +{ +	BOOST_FOREACH(LLToolBarButton* button, mButtons) +	{ +		delete button; +	} +	mButtons.clear(); +	mButtonMap.clear(); +	 +	BOOST_FOREACH(LLCommandId& command_id, mButtonCommands) +	{ +		LLToolBarButton* button = createButton(command_id); +		mButtons.push_back(button); +		mButtonPanel->addChild(button); +		mButtonMap.insert(std::make_pair(command_id, button)); +	} +	mNeedsLayout = true; +} + +LLToolBarButton* LLToolBar::createButton(const LLCommandId& id) +{ +	LLCommand* commandp = LLCommandManager::instance().getCommand(id); +	if (!commandp) return NULL; + +	std::string label = LLTrans::getString(commandp->labelRef()); +	std::string tooltip = label + "\n" + LLTrans::getString(commandp->tooltipRef()); + +	LLToolBarButton::Params button_p; +	button_p.name = id.name(); +	button_p.label = label; +	button_p.tool_tip = tooltip; +	button_p.image_overlay = LLUI::getUIImage(commandp->icon()); +	button_p.overwriteFrom(mButtonParams[mButtonType]); +	LLToolBarButton* button = LLUICtrlFactory::create<LLToolBarButton>(button_p); + +	if (!mReadOnly) +	{ +		LLUICtrl::CommitCallbackParam cbParam; +		cbParam.function_name = commandp->executeFunctionName(); +		cbParam.parameter = commandp->executeParameters(); +		button->setCommitCallback(cbParam); +		button->setStartDragCallback(mStartDragItemCallback); +		button->setHandleDragCallback(mHandleDragItemCallback); +	} + +	button->setCommandId(id); +	return button; + +} + +BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +										EDragAndDropType cargo_type, +										void* cargo_data, +										EAcceptance* accept, +										std::string& tooltip_msg) +{ +	llinfos << "Merov debug : handleDragAndDrop. drop = " << drop << ", x = " << x << ", y = " << y << llendl; +	// If we have a drop callback, that means that we can handle the drop +	BOOL handled = (mHandleDropCallback ? TRUE : FALSE); +	 +	// if drop is set, it's time to call the callback to get the operation done +	if (handled && drop) +	{ +		handled = mHandleDropCallback(cargo_data, x, y ,this); +	} +	 +	// We accept only single tool drop on toolbars +	*accept = (handled ? ACCEPT_YES_SINGLE : ACCEPT_NO); +	 +	// We'll use that flag to change the visual aspect of the toolbar target on draw() +	mDragAndDropTarget = handled; +	 +	return handled; +} + +LLToolBarButton::LLToolBarButton(const Params& p)  +:	LLButton(p), +	mMouseDownX(0), +	mMouseDownY(0), +	mWidthRange(p.button_width), +	mDesiredHeight(p.desired_height), +	mId("") +{ +} + +BOOL LLToolBarButton::handleMouseDown(S32 x, S32 y, MASK mask) +{ +	mMouseDownX = x; +	mMouseDownY = y; +	return LLButton::handleMouseDown(x, y, mask); +} + +BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask) +{ +//	llinfos << "Merov debug: handleHover, x = " << x << ", y = " << y << ", mouse = " << hasMouseCapture() << llendl; +	BOOL handled = FALSE; +		 +	if (hasMouseCapture() && mStartDragItemCallback && mHandleDragItemCallback) +	{ +		if (!mIsDragged) +		{ +			mStartDragItemCallback(x,y,mId.uuid()); +			mIsDragged = true; +			handled = TRUE; +		} +		else  +		{ +			handled = mHandleDragItemCallback(x,y,mId.uuid(),LLAssetType::AT_WIDGET); +		} +	} +	else +	{ +		handled = LLButton::handleHover(x, y, mask); +	} +	return handled; +} + diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h new file mode 100644 index 0000000000..a35f6d9db1 --- /dev/null +++ b/indra/llui/lltoolbar.h @@ -0,0 +1,218 @@ +/**  + * @file lltoolbar.h + * @author Richard Nelson + * @brief User customizable toolbar class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +#ifndef LL_LLTOOLBAR_H +#define LL_LLTOOLBAR_H + +#include "llbutton.h" +#include "llcommandmanager.h" +#include "lllayoutstack.h" +#include "lluictrl.h" +#include "llcommandmanager.h" +#include "llassettype.h" + +class LLToolBar; + +typedef boost::function<void (S32 x, S32 y, const LLUUID& uuid)> tool_startdrag_callback_t; +typedef boost::function<BOOL (S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type)> tool_handledrag_callback_t; +typedef boost::function<BOOL (void* data, S32 x, S32 y, LLToolBar* toolbar)> tool_handledrop_callback_t; + +class LLToolBarButton : public LLButton +{ +	friend class LLToolBar; +public: +	struct Params : public LLInitParam::Block<Params, LLButton::Params> +	{ +		Optional<LLUI::RangeS32>	button_width; +		Optional<S32>				desired_height; + +		Params() +		:	button_width("button_width"), +			desired_height("desired_height", 20) +		{} + +	}; + +	LLToolBarButton(const Params& p); + +	BOOL handleMouseDown(S32 x, S32 y, MASK mask); +	BOOL handleHover(S32 x, S32 y, MASK mask); +	void setCommandId(const LLCommandId& id) { mId = id; } + +	void setStartDragCallback(tool_startdrag_callback_t cb)   { mStartDragItemCallback  = cb; } +	void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; } +private: +	LLCommandId		mId; +	S32				mMouseDownX; +	S32				mMouseDownY; +	LLUI::RangeS32	mWidthRange; +	S32				mDesiredHeight; +	bool							mIsDragged; +	tool_startdrag_callback_t		mStartDragItemCallback; +	tool_handledrag_callback_t		mHandleDragItemCallback; +}; + + +namespace LLToolBarEnums +{ +	enum ButtonType +	{ +		BTNTYPE_ICONS_WITH_TEXT = 0, +		BTNTYPE_ICONS_ONLY, + +		BTNTYPE_COUNT +	}; + +	enum SideType +	{ +		SIDE_BOTTOM, +		SIDE_LEFT, +		SIDE_RIGHT, +		SIDE_TOP, +	}; +} + +// NOTE: This needs to occur before Param block declaration for proper compilation. +namespace LLInitParam +{ +	template<> +	struct TypeValues<LLToolBarEnums::ButtonType> : public TypeValuesHelper<LLToolBarEnums::ButtonType> +	{ +		static void declareValues(); +	}; + +	template<> +	struct TypeValues<LLToolBarEnums::SideType> : public TypeValuesHelper<LLToolBarEnums::SideType> +	{ +		static void declareValues(); +	}; +} + + +class LLToolBar +:	public LLUICtrl +{ +public: +	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> +	{ +		Mandatory<LLToolBarEnums::ButtonType>	button_display_mode; +		Mandatory<LLToolBarEnums::SideType>		side; + +		Optional<LLToolBarButton::Params>		button_icon, +												button_icon_and_text; + +		Optional<bool>							read_only, +												wrap; + +		Optional<S32>							pad_left, +												pad_top, +												pad_right, +												pad_bottom, +												pad_between; +		// get rid of this +		Multiple<LLCommandId::Params>			commands; + +		Optional<LLPanel::Params>				button_panel; + +		Params(); +	}; + +	// virtuals +	void draw(); +	void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +	int  getRankFromPosition(S32 x, S32 y);	 +	BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); +	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +								   EDragAndDropType cargo_type, +								   void* cargo_data, +								   EAcceptance* accept, +								   std::string& tooltip_msg); +	 +	bool addCommand(const LLCommandId& commandId, int rank = -1); +	bool removeCommand(const LLCommandId& commandId); +	bool hasCommand(const LLCommandId& commandId) const; +	bool enableCommand(const LLCommandId& commandId, bool enabled); +	void setStartDragCallback(tool_startdrag_callback_t cb)   { mStartDragItemCallback  = cb; } +	void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; } +	void setHandleDropCallback(tool_handledrop_callback_t cb) { mHandleDropCallback     = cb; } + +	LLToolBarButton* createButton(const LLCommandId& id); + +protected: +	friend class LLUICtrlFactory; +	LLToolBar(const Params&); +	~LLToolBar(); + +	void initFromParams(const Params&); +	tool_startdrag_callback_t		mStartDragItemCallback; +	tool_handledrag_callback_t		mHandleDragItemCallback; +	tool_handledrop_callback_t		mHandleDropCallback; +	bool							mDragAndDropTarget; + +public: +	// Methods used in loading and saving toolbar settings +	void setButtonType(LLToolBarEnums::ButtonType button_type); +	LLToolBarEnums::ButtonType getButtonType() { return mButtonType; } +	command_id_list_t& getCommandsList() { return mButtonCommands; } +	void clearCommandsList(); +					    +private: +	void createContextMenu(); +	void updateLayoutAsNeeded(); +	void createButtons(); +	void resizeButtonsInRow(std::vector<LLToolBarButton*>& buttons_in_row, S32 max_row_girth); +	BOOL isSettingChecked(const LLSD& userdata); +	void onSettingEnable(const LLSD& userdata); + +	const bool						mReadOnly; + +	std::list<LLToolBarButton*>		mButtons; +	command_id_list_t				mButtonCommands; +	typedef std::map<LLCommandId, LLToolBarButton*> command_id_map; +	command_id_map					mButtonMap; + +	LLToolBarEnums::ButtonType		mButtonType; +	LLLayoutStack*					mCenteringStack; +	LLLayoutStack*					mWrapStack; +	LLPanel*						mButtonPanel; +	LLToolBarEnums::SideType		mSideType; + +	bool							mWrap; +	bool							mNeedsLayout; +	S32								mPadLeft, +									mPadRight, +									mPadTop, +									mPadBottom, +									mPadBetween; + +	LLToolBarButton::Params			mButtonParams[LLToolBarEnums::BTNTYPE_COUNT]; + +	LLHandle<class LLContextMenu>			mPopupMenuHandle; +}; + + +#endif  // LL_LLTOOLBAR_H diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 58ba9e05f5..76a12e649b 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -41,6 +41,7 @@  #include "llgl.h"  // Project includes +#include "llcommandmanager.h"  #include "llcontrol.h"  #include "llui.h"  #include "lluicolortable.h" @@ -57,6 +58,7 @@  #include "llfiltereditor.h"  #include "llflyoutbutton.h"  #include "llsearcheditor.h" +#include "lltoolbar.h"  // for XUIParse  #include "llquaternion.h" @@ -94,6 +96,7 @@ static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("  // register other widgets which otherwise may not be linked in  static LLDefaultChildRegistry::Register<LLLoadingIndicator> register_loading_indicator("loading_indicator"); +static LLDefaultChildRegistry::Register<LLToolBar> register_toolbar("toolbar");  //  // Functions @@ -1615,6 +1618,7 @@ void LLUI::initClass(const settings_map_t& settings,  	// Callbacks for associating controls with floater visibilty:  	reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2)); +	reg.add("Floater.ToolbarToggle", boost::bind(&LLFloaterReg::toggleToolbarFloaterInstance, _2));  	reg.add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));  	reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideFloaterInstance, _2));  	reg.add("Floater.InitToVisibilityControl", boost::bind(&LLFloaterReg::initUICtrlToFloaterVisibilityControl, _1, _2)); @@ -1633,6 +1637,9 @@ void LLUI::initClass(const settings_map_t& settings,  	// Used by menus along with Floater.Toggle to display visibility as a checkmark  	LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::floaterInstanceVisible, _2)); + +	// Parse the master list of commands +	LLCommandManager::load();  }  void LLUI::cleanupClass() @@ -2100,7 +2107,7 @@ namespace LLInitParam  	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()  	{ -		if (control.isProvided()) +		if (control.isProvided() && !control().empty())  		{  			updateValue(LLUIColorTable::instance().getColor(control));  		} @@ -2257,9 +2264,11 @@ namespace LLInitParam  		// in this case, that is left+width and bottom+height  		LLRect& value = getValue(); +		right.set(value.mRight, false);  		left.set(value.mLeft, make_block_authoritative);  		width.set(value.getWidth(), make_block_authoritative); +		top.set(value.mTop, false);  		bottom.set(value.mBottom, make_block_authoritative);  		height.set(value.getHeight(), make_block_authoritative);  	} diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 7801a01ace..28e84fa444 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -41,6 +41,7 @@  #include <boost/signals2.hpp>  #include "lllazyvalue.h"  #include "llframetimer.h" +#include <limits>  // LLUIFactory  #include "llsd.h" @@ -148,6 +149,122 @@ class LLUI  	LOG_CLASS(LLUI);  public:  	// +	// Classes +	// + +	struct RangeS32  +	{ +		struct Params : public LLInitParam::Block<Params> +		{ +			Optional<S32>	minimum, +							maximum; + +			Params() +			:	minimum("min", 0), +				maximum("max", S32_MAX) +			{} +		}; + +		// correct for inverted params +		RangeS32(const Params& p = Params()) +		:	mMin(p.minimum), +			mMax(p.maximum) +		{ +			sanitizeRange(); +		} + +		RangeS32(S32 minimum, S32 maximum) +		:	mMin(minimum), +			mMax(maximum) +		{ +			sanitizeRange(); +		} + +		S32 clamp(S32 input) +		{ +			if (input < mMin) return mMin; +			if (input > mMax) return mMax; +			return input; +		} + +		void setRange(S32 minimum, S32 maximum) +		{ +			mMin = minimum; +			mMax = maximum; +			sanitizeRange(); +		} + +		S32 getMin() { return mMin; } +		S32 getMax() { return mMax; } + +		bool operator==(const RangeS32& other) const +		{ +			return mMin == other.mMin  +				&& mMax == other.mMax; +		} +	private: +		void sanitizeRange() +		{ +			if (mMin > mMax) +			{ +				llwarns << "Bad interval range (" << mMin << ", " << mMax << ")" << llendl; +				// since max is usually the most dangerous one to ignore (buffer overflow, etc), prefer it +				// in the case of a malformed range +				mMin = mMax; +			} +		} + + +		S32	mMin, +			mMax; +	}; + +	struct ClampedS32 : public RangeS32 +	{ +		struct Params : public LLInitParam::Block<Params, RangeS32::Params> +		{ +			Mandatory<S32> value; + +			Params() +			:	value("", 0) +			{ +				addSynonym(value, "value"); +			} +		}; + +		ClampedS32(const Params& p) +		:	RangeS32(p) +		{} + +		ClampedS32(const RangeS32& range) +		:	RangeS32(range) +		{ +			// set value here, after range has been sanitized +			mValue = clamp(0); +		} + +		ClampedS32(S32 value, const RangeS32& range = RangeS32()) +		:	RangeS32(range) +		{ +			mValue = clamp(value); +		} + +		S32 get() +		{ +			return mValue; +		} + +		void set(S32 value) +		{ +			mValue = clamp(value); +		} + + +	private: +		S32 mValue; +	}; + +	//  	// Methods  	//  	typedef std::map<std::string, LLControlGroup*> settings_map_t; @@ -365,7 +482,7 @@ template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(  template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass);  // useful parameter blocks -struct TimeIntervalParam : public LLInitParam::Choice<TimeIntervalParam> +struct TimeIntervalParam : public LLInitParam::ChoiceBlock<TimeIntervalParam>  {  	Alternative<F32>		seconds;  	Alternative<S32>		frames; diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h index 76518789ec..6a7a681d57 100644 --- a/indra/llui/lluicolortable.h +++ b/indra/llui/lluicolortable.h @@ -44,7 +44,7 @@ LOG_CLASS(LLUIColorTable);  	typedef std::map<std::string, LLUIColor>  string_color_map_t;  public: -	struct ColorParams : LLInitParam::Choice<ColorParams> +	struct ColorParams : LLInitParam::ChoiceBlock<ColorParams>  	{  		Alternative<LLColor4>    value;  		Alternative<std::string> reference; diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index d58df5801b..5e8bf498c0 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -992,6 +992,16 @@ void LLUICtrl::setTransparencyType(ETypeTransparency type)  	mTransparencyType = type;  } +boost::signals2::connection LLUICtrl::setCommitCallback(const CommitCallbackParam& cb) +{ +	return setCommitCallback(initCommitCallback(cb)); +} + +boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackParam& cb) +{ +	return setValidateCallback(initEnableCallback(cb)); +} +  boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )   {   	if (!mCommitSignal) mCommitSignal = new commit_signal_t(); diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 09bed9b958..a8a4e3191d 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -76,14 +76,14 @@ public:  		Optional<enable_callback_t> function;  	}; -	struct EnableControls : public LLInitParam::Choice<EnableControls> +	struct EnableControls : public LLInitParam::ChoiceBlock<EnableControls>  	{  		Alternative<std::string> enabled;  		Alternative<std::string> disabled;  		EnableControls();  	};	 -	struct ControlVisibility : public LLInitParam::Choice<ControlVisibility> +	struct ControlVisibility : public LLInitParam::ChoiceBlock<ControlVisibility>  	{  		Alternative<std::string> visible;  		Alternative<std::string> invisible; @@ -235,6 +235,9 @@ public:  	// topic then put in help_topic_out  	bool                    findHelpTopic(std::string& help_topic_out); +	boost::signals2::connection setCommitCallback(const CommitCallbackParam& cb); +	boost::signals2::connection setValidateCallback(const EnableCallbackParam& cb); +  	boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb );  	boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb ); diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index d345ad4cd0..d612ad5005 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -125,12 +125,12 @@ private:  	// base case for recursion, there are NO base classes of LLInitParam::BaseBlock  	template<int DUMMY> -	class ParamDefaults<LLInitParam::BaseBlockWithFlags, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlockWithFlags, DUMMY> > +	class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> >  	{  	public: -		const LLInitParam::BaseBlockWithFlags& get() { return mBaseBlock; } +		const LLInitParam::BaseBlock& get() { return mBaseBlock; }  	private: -		LLInitParam::BaseBlockWithFlags mBaseBlock; +		LLInitParam::BaseBlock mBaseBlock;  	};  public: @@ -172,7 +172,7 @@ public:  	static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry, LLXMLNodePtr output_node = NULL)  	{  		T* widget = NULL; - +		  		std::string skinned_filename = findSkinnedFilename(filename);  		instance().pushFileName(filename);  		{ @@ -201,10 +201,10 @@ public:  				// not of right type, so delete it  				if (!widget)   				{ +					llwarns << "Widget in " << filename << " was of type " << typeid(view).name() << " instead of expected type " << typeid(T).name() << llendl;  					delete view;  					view = NULL;  				} -			  			}  		}  fail: diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 60452b9ae4..e10c2f0d1e 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1826,13 +1826,6 @@ LLView* LLView::findNextSibling(LLView* child)  	return (next_it != mChildList.end()) ? *next_it : NULL;  } -void LLView::deleteViewByHandle(LLHandle<LLView> handle) -{ -	LLView* viewp = handle.get(); - -	delete viewp; -} -  LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside)  { diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 594a5eec6b..a1c46f3bf3 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -95,13 +95,10 @@ private:  	static std::vector<LLViewDrawContext*> sDrawContextStack;  }; -class LLViewWidgetRegistry : public LLChildRegistry<LLViewWidgetRegistry> -{}; -  class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElement  {  public: -	struct Follows : public LLInitParam::Choice<Follows> +	struct Follows : public LLInitParam::ChoiceBlock<Follows>  	{  		Alternative<std::string>	string;  		Alternative<U32>			flags; @@ -150,7 +147,8 @@ public:  		Params();  	}; -	typedef LLViewWidgetRegistry child_registry_t; +	// most widgets are valid children of LLView +	typedef LLDefaultChildRegistry child_registry_t;  	void initFromParams(const LLView::Params&); @@ -467,6 +465,20 @@ public:  		return dynamic_cast<T*>(widgetp);  	} +	template <class T> T* getParentByType() const +	{ +		LLView* parent = getParent(); +		while(parent) +		{ +			if (dynamic_cast<T*>(parent)) +			{ +				return static_cast<T*>(parent); +			} +			parent = parent->getParent(); +		} +		return NULL; +	} +  	//////////////////////////////////////////////  	// statics  	////////////////////////////////////////////// @@ -482,7 +494,6 @@ public:  	// return query for iterating over focus roots in tab order  	static const LLCtrlQuery & getFocusRootsQuery(); -	static void deleteViewByHandle(LLHandle<LLView> handle);  	static LLWindow*	getWindow(void) { return LLUI::sWindow; }  	// Set up params after XML load before calling new(),  | 
