diff options
Diffstat (limited to 'indra/newview/lltoolbarview.cpp')
| -rw-r--r-- | indra/newview/lltoolbarview.cpp | 492 | 
1 files changed, 492 insertions, 0 deletions
| diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp new file mode 100644 index 0000000000..21e682f072 --- /dev/null +++ b/indra/newview/lltoolbarview.cpp @@ -0,0 +1,492 @@ +/**  + * @file lltoolbarview.cpp + * @author Merov Linden + * @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 "llviewerprecompiledheaders.h" + +#include "lltoolbarview.h" + +#include "lldir.h" +#include "llxmlnode.h" +#include "lltoolbar.h" +#include "llbutton.h" +#include "lltooldraganddrop.h" +#include "llclipboard.h" + +#include <boost/foreach.hpp> + +LLToolBarView* gToolBarView = NULL; + +static LLDefaultChildRegistry::Register<LLToolBarView> r("toolbar_view"); + +bool isToolDragged() +{ +	return (LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_VIEWER); +} + +LLToolBarView::Toolbar::Toolbar() +:	button_display_mode("button_display_mode"), +	commands("command") +{} + +LLToolBarView::ToolbarSet::ToolbarSet() +:	left_toolbar("left_toolbar"), +	right_toolbar("right_toolbar"), +	bottom_toolbar("bottom_toolbar") +{} + + +LLToolBarView::LLToolBarView(const LLToolBarView::Params& p) +:	LLUICtrl(p), +	mToolbarLeft(NULL), +	mToolbarRight(NULL), +	mToolbarBottom(NULL) +{ +} + +void LLToolBarView::initFromParams(const LLToolBarView::Params& p) +{ +	// Initialize the base object +	LLUICtrl::initFromParams(p); +} + +LLToolBarView::~LLToolBarView() +{ +	saveToolbars(); +} + +BOOL LLToolBarView::postBuild() +{ +	mToolbarLeft   = getChild<LLToolBar>("toolbar_left"); +	mToolbarRight  = getChild<LLToolBar>("toolbar_right"); +	mToolbarBottom = getChild<LLToolBar>("toolbar_bottom"); + +	mToolbarLeft->setStartDragCallback(boost::bind(LLToolBarView::startDragTool,_1,_2,_3)); +	mToolbarLeft->setHandleDragCallback(boost::bind(LLToolBarView::handleDragTool,_1,_2,_3,_4)); +	mToolbarLeft->setHandleDropCallback(boost::bind(LLToolBarView::handleDropTool,_1,_2,_3,_4)); +	 +	mToolbarRight->setStartDragCallback(boost::bind(LLToolBarView::startDragTool,_1,_2,_3)); +	mToolbarRight->setHandleDragCallback(boost::bind(LLToolBarView::handleDragTool,_1,_2,_3,_4)); +	mToolbarRight->setHandleDropCallback(boost::bind(LLToolBarView::handleDropTool,_1,_2,_3,_4)); +	 +	mToolbarBottom->setStartDragCallback(boost::bind(LLToolBarView::startDragTool,_1,_2,_3)); +	mToolbarBottom->setHandleDragCallback(boost::bind(LLToolBarView::handleDragTool,_1,_2,_3,_4)); +	mToolbarBottom->setHandleDropCallback(boost::bind(LLToolBarView::handleDropTool,_1,_2,_3,_4)); +	 +	return TRUE; +} + +bool LLToolBarView::hasCommand(const LLCommandId& commandId) const +{ +	bool has_command = false; +	if (mToolbarLeft && !has_command) +	{ +		has_command = mToolbarLeft->hasCommand(commandId); +	} +	if (mToolbarRight && !has_command) +	{ +		has_command = mToolbarRight->hasCommand(commandId); +	} +	if (mToolbarBottom && !has_command) +	{ +		has_command = mToolbarBottom->hasCommand(commandId); +	} +	return has_command; +} + +bool LLToolBarView::addCommand(const LLCommandId& command, LLToolBar* toolbar) +{ +	LLCommandManager& mgr = LLCommandManager::instance(); +	if (mgr.getCommand(command)) +	{ +		toolbar->addCommand(command); +	} +	else  +	{ +		llwarns	<< "Toolbars creation : the command " << command.name() << " cannot be found in the command manager" << llendl; +		return false; +	} +	return true; +} + +bool LLToolBarView::loadToolbars(bool force_default) +{ +	LLToolBarView::ToolbarSet toolbar_set; +	 +	// Load the toolbars.xml file +	std::string toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml"); +	if (force_default) +	{ +		toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "toolbars.xml"); +	} +	else if (!gDirUtilp->fileExists(toolbar_file))  +	{ +		llwarns << "User toolbars def not found -> use default" << llendl; +		toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "toolbars.xml"); +	} +	 +	LLXMLNodePtr root; +	if(!LLXMLNode::parseFile(toolbar_file, root, NULL)) +	{ +		llwarns << "Unable to load toolbars from file: " << toolbar_file << llendl; +		return false; +	} +	if(!root->hasName("toolbars")) +	{ +		llwarns << toolbar_file << " is not a valid toolbars definition file" << llendl; +		return false; +	} +	 +	// Parse the toolbar settings +	LLXUIParser parser; +	parser.readXUI(root, toolbar_set, toolbar_file); +	if (!toolbar_set.validateBlock()) +	{ +		llerrs << "Unable to validate toolbars from file: " << toolbar_file << llendl; +		return false; +	} +	 +	// Clear the toolbars now before adding the loaded commands and settings +	if (mToolbarLeft) +	{ +		mToolbarLeft->clearCommandsList(); +	} +	if (mToolbarRight) +	{ +		mToolbarRight->clearCommandsList(); +	} +	if (mToolbarBottom) +	{ +		mToolbarBottom->clearCommandsList(); +	} +	 +	// Add commands to each toolbar +	if (toolbar_set.left_toolbar.isProvided() && mToolbarLeft) +	{ +		if (toolbar_set.left_toolbar.button_display_mode.isProvided()) +		{ +			LLToolBarEnums::ButtonType button_type = toolbar_set.left_toolbar.button_display_mode; +			mToolbarLeft->setButtonType(button_type); +		} +		BOOST_FOREACH(LLCommandId::Params& command, toolbar_set.left_toolbar.commands) +		{ +			addCommand(LLCommandId(command),mToolbarLeft); +		} +	} +	if (toolbar_set.right_toolbar.isProvided() && mToolbarRight) +	{ +		if (toolbar_set.right_toolbar.button_display_mode.isProvided()) +		{ +			LLToolBarEnums::ButtonType button_type = toolbar_set.right_toolbar.button_display_mode; +			mToolbarRight->setButtonType(button_type); +		} +		BOOST_FOREACH(LLCommandId::Params& command, toolbar_set.right_toolbar.commands) +		{ +			addCommand(LLCommandId(command),mToolbarRight); +		} +	} +	if (toolbar_set.bottom_toolbar.isProvided() && mToolbarBottom) +	{ +		if (toolbar_set.bottom_toolbar.button_display_mode.isProvided()) +		{ +			LLToolBarEnums::ButtonType button_type = toolbar_set.bottom_toolbar.button_display_mode; +			mToolbarBottom->setButtonType(button_type); +		} +		BOOST_FOREACH(LLCommandId::Params& command, toolbar_set.bottom_toolbar.commands) +		{ +			addCommand(LLCommandId(command),mToolbarBottom); +		} +	} +	return true; +} + +//static +bool LLToolBarView::loadDefaultToolbars() +{ +	bool retval = false; + +	if (gToolBarView) +	{ +		retval = gToolBarView->loadToolbars(true); +	} + +	return retval; +} + +void LLToolBarView::saveToolbars() const +{ +	// Build the parameter tree from the toolbar data +	LLToolBarView::ToolbarSet toolbar_set; +	if (mToolbarLeft) +	{ +		toolbar_set.left_toolbar.button_display_mode = mToolbarLeft->getButtonType(); +		addToToolset(mToolbarLeft->getCommandsList(),toolbar_set.left_toolbar); +	} +	if (mToolbarRight) +	{ +		toolbar_set.right_toolbar.button_display_mode = mToolbarRight->getButtonType(); +		addToToolset(mToolbarRight->getCommandsList(),toolbar_set.right_toolbar); +	} +	if (mToolbarBottom) +	{ +		toolbar_set.bottom_toolbar.button_display_mode = mToolbarBottom->getButtonType(); +		addToToolset(mToolbarBottom->getCommandsList(),toolbar_set.bottom_toolbar); +	} +	 +	// Serialize the parameter tree +	LLXMLNodePtr output_node = new LLXMLNode("toolbars", false); +	LLXUIParser parser; +	parser.writeXUI(output_node, toolbar_set); +	 +	// Write the resulting XML to file +	if(!output_node->isNull()) +	{ +		const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml"); +		LLFILE *fp = LLFile::fopen(filename, "w"); +		if (fp != NULL) +		{ +			LLXMLNode::writeHeaderToFile(fp); +			output_node->writeToFile(fp); +			fclose(fp); +		} +	} +} + +// Enumerate the commands in command_list and add them as Params to the toolbar +void LLToolBarView::addToToolset(command_id_list_t& command_list, Toolbar& toolbar) const +{ +	for (command_id_list_t::const_iterator it = command_list.begin(); +		 it != command_list.end(); +		 ++it) +	{ +		LLCommandId::Params command; +		command.name = it->name();		 +		toolbar.commands.add(command); +	} +} + +void LLToolBarView::draw() +{ +	//LLPanel* sizer_left = getChild<LLPanel>("sizer_left"); +	 +	LLRect bottom_rect, left_rect, right_rect; + +	if (mToolbarBottom)  +	{ +		mToolbarBottom->getParent()->reshape(mToolbarBottom->getParent()->getRect().getWidth(), mToolbarBottom->getRect().getHeight()); +		mToolbarBottom->localRectToOtherView(mToolbarBottom->getLocalRect(), &bottom_rect, this); +	} +	if (mToolbarLeft)    +	{ +		mToolbarLeft->getParent()->reshape(mToolbarLeft->getRect().getWidth(), mToolbarLeft->getParent()->getRect().getHeight()); +		mToolbarLeft->localRectToOtherView(mToolbarLeft->getLocalRect(), &left_rect, this); +	} +	if (mToolbarRight)   +	{ +		mToolbarRight->getParent()->reshape(mToolbarRight->getRect().getWidth(), mToolbarRight->getParent()->getRect().getHeight()); +		mToolbarRight->localRectToOtherView(mToolbarRight->getLocalRect(), &right_rect, this); +	} +	 +	// Draw drop zones if drop of a tool is active +	if (isToolDragged()) +	{ +		LLColor4 drop_color = LLUIColorTable::instance().getColor( "ToolbarDropZoneColor" ); +		gl_rect_2d(bottom_rect, drop_color, TRUE); +		gl_rect_2d(left_rect, drop_color, TRUE); +		gl_rect_2d(right_rect, drop_color, TRUE); +	} +	 +	LLUICtrl::draw(); +} + + +// ---------------------------------------- +// Drag and Drop Handling +// ---------------------------------------- + + +void LLToolBarView::startDragTool( S32 x, S32 y, const LLUUID& uuid) +{ +	// Flag the tool dragging but don't start it yet +	gToolBarView->mDragStarted = false; +	gToolBarView->mDragCommand = LLCommandId::null; +	gToolBarView->mDragRank = LLToolBar::RANK_NONE; +	gToolBarView->mDragToolbar = NULL; +	LLToolDragAndDrop::getInstance()->setDragStart( x, y ); +} + +BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type) +{ +	if (LLToolDragAndDrop::getInstance()->isOverThreshold( x, y )) +	{ +		if (!gToolBarView->mDragStarted) +		{ +			// Start the tool dragging: +			 +			// First, create the global drag and drop object +			std::vector<EDragAndDropType> types; +			uuid_vec_t cargo_ids; +			types.push_back(DAD_WIDGET); +			cargo_ids.push_back(uuid); +			gClipboard.setSourceObject(uuid,LLAssetType::AT_WIDGET); +			LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_VIEWER; +			LLUUID srcID; +			LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src, srcID); +			 +			// Second, check if the command is present in one of the 3 toolbars +			// If it is, store the command, the toolbar and the rank in the toolbar and +			// set a callback on end drag so that we reinsert the command if no drop happened +			/* +			gToolBarView->mDragCommand = LLCommandId(uuid); +			if ((gToolBarView->mDragRank = gToolBarView->mToolbarLeft->removeCommand(gToolBarView->mDragCommand)) != LLToolBar::RANK_NONE) +			{ +				gToolBarView->mDragToolbar = gToolBarView->mToolbarLeft; +			} +			else if ((gToolBarView->mDragRank = gToolBarView->mToolbarRight->removeCommand(gToolBarView->mDragCommand)) != LLToolBar::RANK_NONE) +			{ +				gToolBarView->mDragToolbar = gToolBarView->mToolbarRight; +			} +			else if ((gToolBarView->mDragRank = gToolBarView->mToolbarBottom->removeCommand(gToolBarView->mDragCommand)) != LLToolBar::RANK_NONE) +			{ +				gToolBarView->mDragToolbar = gToolBarView->mToolbarBottom; +			} +			if (gToolBarView->mDragRank != LLToolBar::RANK_NONE) +			{ +				llinfos << "Merov debug: rank of dragged tool = " << gToolBarView->mDragRank << llendl; +				LLToolDragAndDrop::getInstance()->setEndDragCallback(boost::bind(&LLToolBarView::onEndDrag, gToolBarView)); +			} +			 */ + +			gToolBarView->mDragStarted = true; +			return TRUE; +		} +		else +		{ +			MASK mask = 0; +			return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); +		} +	} +	return FALSE; +} + +BOOL LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar) +{ +	BOOL handled = FALSE; +	LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; +	 +	LLAssetType::EType type = inv_item->getType(); +	if (type == LLAssetType::AT_WIDGET) +	{ +		handled = TRUE; +		// Get the command from its uuid +		LLCommandManager& mgr = LLCommandManager::instance(); +		LLCommandId command_id(inv_item->getUUID()); +		LLCommand* command = mgr.getCommand(command_id); +		if (command) +		{ +			// Convert the (x,y) position in rank in toolbar +			int new_rank = LLToolBar::RANK_NONE; +			if (!toolbar->isReadOnly()) +			{ +				new_rank = toolbar->getRankFromPosition(x,y); +			} +			// Suppress the command from the toolbars (including the one it's dropped in,  +			// this will handle move position). +			int old_rank = LLToolBar::RANK_NONE; +			LLToolBar* old_toolbar = NULL; +			int rank; +			if ((rank = gToolBarView->mToolbarLeft->removeCommand(command_id)) != LLToolBar::RANK_NONE) +			{ +				old_rank = rank; +				old_toolbar = gToolBarView->mToolbarLeft; +			} +			if ((rank = gToolBarView->mToolbarRight->removeCommand(command_id)) != LLToolBar::RANK_NONE) +			{ +				old_rank = rank; +				old_toolbar = gToolBarView->mToolbarRight; +			} +			if ((rank = gToolBarView->mToolbarBottom->removeCommand(command_id)) != LLToolBar::RANK_NONE) +			{ +				old_rank = rank; +				old_toolbar = gToolBarView->mToolbarBottom; +			} +			// Now insert it in the toolbar at the detected rank +			if (!toolbar->isReadOnly()) +			{ +				if ((old_toolbar == toolbar) && (old_rank != LLToolBar::RANK_NONE) && (old_rank < new_rank)) +				{ +					// If we just removed the command from the same toolbar, we need to consider that it might +					// change the target rank. +					new_rank -= 1; +				} +				toolbar->addCommand(command->id(),new_rank); +			} +		} +		else +		{ +			llwarns << "Command couldn't be found in command manager" << llendl; +		} +	} +	stopDragTool(); +	return handled; +} + +void LLToolBarView::stopDragTool() +{ +	// Clear the saved command, toolbar and rank +	gToolBarView->mDragStarted = false; +	gToolBarView->mDragCommand = LLCommandId::null; +	gToolBarView->mDragRank = LLToolBar::RANK_NONE; +	gToolBarView->mDragToolbar = NULL; +} + +void LLToolBarView::onEndDrag() +{ +	// If there's a saved command, reinsert it in the saved toolbar +	if (gToolBarView->mDragRank != LLToolBar::RANK_NONE) +	{ +		gToolBarView->mDragToolbar->addCommand(gToolBarView->mDragCommand,gToolBarView->mDragRank); +	} +	stopDragTool(); +} + +void LLToolBarView::setToolBarsVisible(bool visible) +{ +	mToolbarBottom->getParent()->setVisible(visible); +	mToolbarLeft->getParent()->setVisible(visible); +	mToolbarRight->getParent()->setVisible(visible); +} + +bool LLToolBarView::isModified() const +{ +	bool modified = false; + +	modified |= mToolbarBottom->isModified(); +	modified |= mToolbarLeft->isModified(); +	modified |= mToolbarRight->isModified(); + +	return modified; +} | 
