PageRenderTime 91ms CodeModel.GetById 3ms app.highlight 72ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/lltoolbarview.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 697 lines | 525 code | 109 blank | 63 comment | 100 complexity | 655549b13943feeb074c7b4966aedd28 MD5 | raw file
  1/** 
  2 * @file lltoolbarview.cpp
  3 * @author Merov Linden
  4 * @brief User customizable toolbar class
  5 *
  6 * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2011, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#include "llviewerprecompiledheaders.h"
 29
 30#include "lltoolbarview.h"
 31
 32#include "llappviewer.h"
 33#include "llbutton.h"
 34#include "llclipboard.h"
 35#include "lldir.h"
 36#include "lldockablefloater.h"
 37#include "lldockcontrol.h"
 38#include "llimview.h"
 39#include "lltransientfloatermgr.h"
 40#include "lltoolbar.h"
 41#include "lltooldraganddrop.h"
 42#include "llxmlnode.h"
 43
 44#include "llagent.h"  // HACK for destinations guide on startup
 45#include "llfloaterreg.h"  // HACK for destinations guide on startup
 46#include "llviewercontrol.h"  // HACK for destinations guide on startup
 47
 48#include <boost/foreach.hpp>
 49
 50LLToolBarView* gToolBarView = NULL;
 51
 52static LLDefaultChildRegistry::Register<LLToolBarView> r("toolbar_view");
 53
 54void handleLoginToolbarSetup();
 55
 56bool isToolDragged()
 57{
 58	return (LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_VIEWER);
 59}
 60
 61LLToolBarView::Toolbar::Toolbar()
 62:	button_display_mode("button_display_mode"),
 63	commands("command")
 64{}
 65
 66LLToolBarView::ToolbarSet::ToolbarSet()
 67:	left_toolbar("left_toolbar"),
 68	right_toolbar("right_toolbar"),
 69	bottom_toolbar("bottom_toolbar")
 70{}
 71
 72
 73LLToolBarView::LLToolBarView(const LLToolBarView::Params& p)
 74:	LLUICtrl(p),
 75	mDragStarted(false),
 76	mShowToolbars(true),
 77	mDragToolbarButton(NULL),
 78	mToolbarsLoaded(false)
 79{
 80	for (S32 i = 0; i < TOOLBAR_COUNT; i++)
 81	{
 82		mToolbars[i] = NULL;
 83	}
 84}
 85
 86void LLToolBarView::initFromParams(const LLToolBarView::Params& p)
 87{
 88	// Initialize the base object
 89	LLUICtrl::initFromParams(p);
 90}
 91
 92LLToolBarView::~LLToolBarView()
 93{
 94	saveToolbars();
 95}
 96
 97BOOL LLToolBarView::postBuild()
 98{
 99	mToolbars[TOOLBAR_LEFT]   = getChild<LLToolBar>("toolbar_left");
100	mToolbars[TOOLBAR_RIGHT]  = getChild<LLToolBar>("toolbar_right");
101	mToolbars[TOOLBAR_BOTTOM] = getChild<LLToolBar>("toolbar_bottom");
102
103	for (int i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
104	{
105		mToolbars[i]->setStartDragCallback(boost::bind(LLToolBarView::startDragTool,_1,_2,_3));
106		mToolbars[i]->setHandleDragCallback(boost::bind(LLToolBarView::handleDragTool,_1,_2,_3,_4));
107		mToolbars[i]->setHandleDropCallback(boost::bind(LLToolBarView::handleDropTool,_1,_2,_3,_4));
108		mToolbars[i]->setButtonAddCallback(boost::bind(LLToolBarView::onToolBarButtonAdded,_1));
109		mToolbars[i]->setButtonRemoveCallback(boost::bind(LLToolBarView::onToolBarButtonRemoved,_1));
110	}
111
112	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&handleLoginToolbarSetup));
113	
114	return TRUE;
115}
116
117S32 LLToolBarView::hasCommand(const LLCommandId& commandId) const
118{
119	S32 command_location = TOOLBAR_NONE;
120
121	for (S32 loc = TOOLBAR_FIRST; loc <= TOOLBAR_LAST; loc++)
122	{
123		if (mToolbars[loc]->hasCommand(commandId))
124		{
125			command_location = loc;
126			break;
127		}
128	}
129
130	return command_location;
131}
132
133S32 LLToolBarView::addCommand(const LLCommandId& commandId, EToolBarLocation toolbar, int rank)
134{
135	int old_rank;
136	removeCommand(commandId, old_rank);
137
138	S32 command_location = mToolbars[toolbar]->addCommand(commandId, rank);
139
140	return command_location;
141}
142
143S32 LLToolBarView::removeCommand(const LLCommandId& commandId, int& rank)
144{
145	S32 command_location = hasCommand(commandId);
146	rank = LLToolBar::RANK_NONE;
147
148	if (command_location != TOOLBAR_NONE)
149	{
150		rank = mToolbars[command_location]->removeCommand(commandId);
151	}
152
153	return command_location;
154}
155
156S32 LLToolBarView::enableCommand(const LLCommandId& commandId, bool enabled)
157{
158	S32 command_location = hasCommand(commandId);
159
160	if (command_location != TOOLBAR_NONE)
161	{
162		mToolbars[command_location]->enableCommand(commandId, enabled);
163	}
164
165	return command_location;
166}
167
168S32 LLToolBarView::stopCommandInProgress(const LLCommandId& commandId)
169{
170	S32 command_location = hasCommand(commandId);
171
172	if (command_location != TOOLBAR_NONE)
173	{
174		mToolbars[command_location]->stopCommandInProgress(commandId);
175	}
176
177	return command_location;
178}
179
180S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash)
181{
182	S32 command_location = hasCommand(commandId);
183
184	if (command_location != TOOLBAR_NONE)
185	{
186		mToolbars[command_location]->flashCommand(commandId, flash);
187	}
188
189	return command_location;
190}
191
192bool LLToolBarView::addCommandInternal(const LLCommandId& command, LLToolBar* toolbar)
193{
194	LLCommandManager& mgr = LLCommandManager::instance();
195	if (mgr.getCommand(command))
196	{
197		toolbar->addCommand(command);
198	}
199	else 
200	{
201		llwarns	<< "Toolbars creation : the command with id " << command.uuid().asString() << " cannot be found in the command manager" << llendl;
202		return false;
203	}
204	return true;
205}
206
207bool LLToolBarView::loadToolbars(bool force_default)
208{
209	LLToolBarView::ToolbarSet toolbar_set;
210	bool err = false;
211	
212	// Load the toolbars.xml file
213	std::string toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml");
214	if (force_default)
215	{
216		toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "toolbars.xml");
217	}
218	else if (!gDirUtilp->fileExists(toolbar_file)) 
219	{
220		llwarns << "User toolbars def not found -> use default" << llendl;
221		toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "toolbars.xml");
222	}
223	
224	LLXMLNodePtr root;
225	if(!LLXMLNode::parseFile(toolbar_file, root, NULL))
226	{
227		llwarns << "Unable to load toolbars from file: " << toolbar_file << llendl;
228		err = true;
229	}
230	
231	if (!err && !root->hasName("toolbars"))
232	{
233		llwarns << toolbar_file << " is not a valid toolbars definition file" << llendl;
234		err = true;
235	}
236	
237	// Parse the toolbar settings
238	LLXUIParser parser;
239	if (!err)
240	{
241	parser.readXUI(root, toolbar_set, toolbar_file);
242	}
243	if (!err && !toolbar_set.validateBlock())
244	{
245		llwarns << "Unable to validate toolbars from file: " << toolbar_file << llendl;
246		err = true;
247	}
248	
249	if (err)
250	{
251		if (force_default)
252		{
253			llerrs << "Unable to load toolbars from default file : " << toolbar_file << llendl;
254		return false;
255	}
256		// Try to load the default toolbars
257		return loadToolbars(true);
258	}
259	
260	// Clear the toolbars now before adding the loaded commands and settings
261	for (S32 i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
262	{
263		if (mToolbars[i])
264		{
265			mToolbars[i]->clearCommandsList();
266		}
267	}
268	
269	// Add commands to each toolbar
270	if (toolbar_set.left_toolbar.isProvided() && mToolbars[TOOLBAR_LEFT])
271	{
272		if (toolbar_set.left_toolbar.button_display_mode.isProvided())
273		{
274			LLToolBarEnums::ButtonType button_type = toolbar_set.left_toolbar.button_display_mode;
275			mToolbars[TOOLBAR_LEFT]->setButtonType(button_type);
276		}
277		BOOST_FOREACH(const LLCommandId::Params& command_params, toolbar_set.left_toolbar.commands)
278		{
279			if (addCommandInternal(LLCommandId(command_params), mToolbars[TOOLBAR_LEFT]))
280			{
281				llwarns << "Error adding command '" << command_params.name() << "' to left toolbar." << llendl;
282			}
283		}
284	}
285	if (toolbar_set.right_toolbar.isProvided() && mToolbars[TOOLBAR_RIGHT])
286	{
287		if (toolbar_set.right_toolbar.button_display_mode.isProvided())
288		{
289			LLToolBarEnums::ButtonType button_type = toolbar_set.right_toolbar.button_display_mode;
290			mToolbars[TOOLBAR_RIGHT]->setButtonType(button_type);
291		}
292		BOOST_FOREACH(const LLCommandId::Params& command_params, toolbar_set.right_toolbar.commands)
293		{
294			if (addCommandInternal(LLCommandId(command_params), mToolbars[TOOLBAR_RIGHT]))
295			{
296				llwarns << "Error adding command '" << command_params.name() << "' to right toolbar." << llendl;
297			}
298		}
299	}
300	if (toolbar_set.bottom_toolbar.isProvided() && mToolbars[TOOLBAR_BOTTOM])
301	{
302		if (toolbar_set.bottom_toolbar.button_display_mode.isProvided())
303		{
304			LLToolBarEnums::ButtonType button_type = toolbar_set.bottom_toolbar.button_display_mode;
305			mToolbars[TOOLBAR_BOTTOM]->setButtonType(button_type);
306		}
307		BOOST_FOREACH(const LLCommandId::Params& command_params, toolbar_set.bottom_toolbar.commands)
308		{
309			if (addCommandInternal(LLCommandId(command_params), mToolbars[TOOLBAR_BOTTOM]))
310			{
311				llwarns << "Error adding command '" << command_params.name() << "' to bottom toolbar." << llendl;
312			}
313		}
314	}
315	mToolbarsLoaded = true;
316	return true;
317}
318
319bool LLToolBarView::clearToolbars()
320{
321	for (S32 i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
322	{
323		if (mToolbars[i])
324		{
325			mToolbars[i]->clearCommandsList();
326		}
327	}
328
329	return true;
330}
331
332//static
333bool LLToolBarView::loadDefaultToolbars()
334{
335	bool retval = false;
336
337	if (gToolBarView)
338	{
339		retval = gToolBarView->loadToolbars(true);
340		if (retval)
341		{
342			gToolBarView->saveToolbars();
343		}
344	}
345
346	return retval;
347}
348
349//static
350bool LLToolBarView::clearAllToolbars()
351{
352	bool retval = false;
353
354	if (gToolBarView)
355	{
356		retval = gToolBarView->clearToolbars();
357		if (retval)
358		{
359			gToolBarView->saveToolbars();
360		}
361	}
362
363	return retval;
364}
365
366void LLToolBarView::saveToolbars() const
367{
368	if (!mToolbarsLoaded)
369		return;
370	
371	// Build the parameter tree from the toolbar data
372	LLToolBarView::ToolbarSet toolbar_set;
373	if (mToolbars[TOOLBAR_LEFT])
374	{
375		toolbar_set.left_toolbar.button_display_mode = mToolbars[TOOLBAR_LEFT]->getButtonType();
376		addToToolset(mToolbars[TOOLBAR_LEFT]->getCommandsList(), toolbar_set.left_toolbar);
377	}
378	if (mToolbars[TOOLBAR_RIGHT])
379	{
380		toolbar_set.right_toolbar.button_display_mode = mToolbars[TOOLBAR_RIGHT]->getButtonType();
381		addToToolset(mToolbars[TOOLBAR_RIGHT]->getCommandsList(), toolbar_set.right_toolbar);
382	}
383	if (mToolbars[TOOLBAR_BOTTOM])
384	{
385		toolbar_set.bottom_toolbar.button_display_mode = mToolbars[TOOLBAR_BOTTOM]->getButtonType();
386		addToToolset(mToolbars[TOOLBAR_BOTTOM]->getCommandsList(), toolbar_set.bottom_toolbar);
387	}
388	
389	// Serialize the parameter tree
390	LLXMLNodePtr output_node = new LLXMLNode("toolbars", false);
391	LLXUIParser parser;
392	parser.writeXUI(output_node, toolbar_set);
393	
394	// Write the resulting XML to file
395	if(!output_node->isNull())
396	{
397		const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml");
398		LLFILE *fp = LLFile::fopen(filename, "w");
399		if (fp != NULL)
400		{
401			LLXMLNode::writeHeaderToFile(fp);
402			output_node->writeToFile(fp);
403			fclose(fp);
404		}
405	}
406}
407
408// Enumerate the commands in command_list and add them as Params to the toolbar
409void LLToolBarView::addToToolset(command_id_list_t& command_list, Toolbar& toolbar) const
410{
411	LLCommandManager& mgr = LLCommandManager::instance();
412
413	for (command_id_list_t::const_iterator it = command_list.begin();
414		 it != command_list.end();
415		 ++it)
416	{
417		LLCommand* command = mgr.getCommand(*it);
418		if (command)
419		{
420			LLCommandId::Params command_name_param;
421			command_name_param.name = command->name();
422			toolbar.commands.add(command_name_param);
423		}
424	}
425}
426
427void LLToolBarView::onToolBarButtonAdded(LLView* button)
428{
429	llassert(button);
430	
431	if (button->getName() == "speak")
432	{
433		// Add the "Speak" button as a control view in LLTransientFloaterMgr
434		// to prevent hiding the transient IM floater upon pressing "Speak".
435		LLTransientFloaterMgr::getInstance()->addControlView(button);
436		
437		// Redock incoming and/or outgoing call windows, if applicable
438		
439		LLFloater* incoming_floater = LLFloaterReg::getLastFloaterInGroup("incoming_call");
440		LLFloater* outgoing_floater = LLFloaterReg::getLastFloaterInGroup("outgoing_call");
441		
442		if (incoming_floater && incoming_floater->isShown())
443		{
444			LLCallDialog* incoming = dynamic_cast<LLCallDialog *>(incoming_floater);
445			llassert(incoming);
446			
447			LLDockControl* dock_control = incoming->getDockControl();
448			if (dock_control->getDock() == NULL)
449			{
450				incoming->dockToToolbarButton("speak");
451			}
452		}
453		
454		if (outgoing_floater && outgoing_floater->isShown())
455		{
456			LLCallDialog* outgoing = dynamic_cast<LLCallDialog *>(outgoing_floater);
457			llassert(outgoing);
458			
459			LLDockControl* dock_control = outgoing->getDockControl();
460			if (dock_control->getDock() == NULL)
461			{
462				outgoing->dockToToolbarButton("speak");
463			}
464		}
465	}
466	else if (button->getName() == "voice")
467	{
468		// Add the "Voice controls" button as a control view in LLTransientFloaterMgr
469		// to prevent hiding the transient IM floater upon pressing "Voice controls".
470		LLTransientFloaterMgr::getInstance()->addControlView(button);
471	}
472}
473
474void LLToolBarView::onToolBarButtonRemoved(LLView* button)
475{
476	llassert(button);
477
478	if (button->getName() == "speak")
479	{
480		LLTransientFloaterMgr::getInstance()->removeControlView(button);
481		
482		// Undock incoming and/or outgoing call windows
483		
484		LLFloater* incoming_floater = LLFloaterReg::getLastFloaterInGroup("incoming_call");
485		LLFloater* outgoing_floater = LLFloaterReg::getLastFloaterInGroup("outgoing_call");
486		
487		if (incoming_floater && incoming_floater->isShown())
488		{
489			LLDockableFloater* incoming = dynamic_cast<LLDockableFloater *>(incoming_floater);
490			llassert(incoming);
491
492			LLDockControl* dock_control = incoming->getDockControl();
493			dock_control->setDock(NULL);
494		}
495		
496		if (outgoing_floater && outgoing_floater->isShown())
497		{
498			LLDockableFloater* outgoing = dynamic_cast<LLDockableFloater *>(outgoing_floater);
499			llassert(outgoing);
500
501			LLDockControl* dock_control = outgoing->getDockControl();
502			dock_control->setDock(NULL);
503		}
504	}
505	else if (button->getName() == "voice")
506	{
507		LLTransientFloaterMgr::getInstance()->removeControlView(button);
508	}
509}
510
511void LLToolBarView::draw()
512{
513	LLRect toolbar_rects[TOOLBAR_COUNT];
514	
515	for (S32 i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
516	{
517		if (mToolbars[i])
518		{
519			LLLayoutStack::ELayoutOrientation orientation = LLToolBarEnums::getOrientation(mToolbars[i]->getSideType());
520
521			if (orientation == LLLayoutStack::HORIZONTAL)
522			{
523				mToolbars[i]->getParent()->reshape(mToolbars[i]->getParent()->getRect().getWidth(), mToolbars[i]->getRect().getHeight());
524			}
525			else
526			{
527				mToolbars[i]->getParent()->reshape(mToolbars[i]->getRect().getWidth(), mToolbars[i]->getParent()->getRect().getHeight());
528			}
529
530			mToolbars[i]->localRectToOtherView(mToolbars[i]->getLocalRect(), &toolbar_rects[i], this);
531		}
532	}
533	
534	for (S32 i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
535	{
536		mToolbars[i]->getParent()->setVisible(mShowToolbars 
537											&& (mToolbars[i]->hasButtons() 
538											|| isToolDragged()));
539	}
540
541	// Draw drop zones if drop of a tool is active
542	if (isToolDragged())
543	{
544		LLColor4 drop_color = LLUIColorTable::instance().getColor( "ToolbarDropZoneColor" );
545
546		for (S32 i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
547		{
548			gl_rect_2d(toolbar_rects[i], drop_color, TRUE);
549		}
550	}
551	
552	LLUICtrl::draw();
553}
554
555
556// ----------------------------------------
557// Drag and Drop Handling
558// ----------------------------------------
559
560
561void LLToolBarView::startDragTool(S32 x, S32 y, LLToolBarButton* toolbarButton)
562{
563	resetDragTool(toolbarButton);
564
565	// Flag the tool dragging but don't start it yet
566	LLToolDragAndDrop::getInstance()->setDragStart( x, y );
567}
568
569BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type)
570{
571	if (LLToolDragAndDrop::getInstance()->isOverThreshold( x, y ))
572	{
573		if (!gToolBarView->mDragStarted)
574		{
575			// Start the tool dragging:
576			
577			// First, create the global drag and drop object
578			std::vector<EDragAndDropType> types;
579			uuid_vec_t cargo_ids;
580			types.push_back(DAD_WIDGET);
581			cargo_ids.push_back(uuid);
582			gClipboard.setSourceObject(uuid,LLAssetType::AT_WIDGET);
583			LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_VIEWER;
584			LLUUID srcID;
585			LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src, srcID);
586
587			// Second, stop the command if it is in progress and requires stopping!
588			LLCommandId command_id = LLCommandId(uuid);
589			gToolBarView->stopCommandInProgress(command_id);
590
591			gToolBarView->mDragStarted = true;
592			return TRUE;
593		}
594		else
595		{
596			MASK mask = 0;
597			return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
598		}
599	}
600	return FALSE;
601}
602
603BOOL LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar)
604{
605	BOOL handled = FALSE;
606	LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
607	
608	LLAssetType::EType type = inv_item->getType();
609	if (type == LLAssetType::AT_WIDGET)
610	{
611		handled = TRUE;
612		// Get the command from its uuid
613		LLCommandManager& mgr = LLCommandManager::instance();
614		LLCommandId command_id(inv_item->getUUID());
615		LLCommand* command = mgr.getCommand(command_id);
616		if (command)
617		{
618			// Suppress the command from the toolbars (including the one it's dropped in, 
619			// this will handle move position).
620			S32 old_toolbar_loc = gToolBarView->hasCommand(command_id);
621			LLToolBar* old_toolbar = NULL;
622
623			if (old_toolbar_loc != TOOLBAR_NONE)
624			{
625				llassert(gToolBarView->mDragToolbarButton);
626				old_toolbar = gToolBarView->mDragToolbarButton->getParentByType<LLToolBar>();
627				if (old_toolbar->isReadOnly() && toolbar->isReadOnly())
628				{
629					// do nothing
630				}
631				else
632				{
633					int old_rank = LLToolBar::RANK_NONE;
634					gToolBarView->removeCommand(command_id, old_rank);
635				}
636			}
637
638			// Convert the (x,y) position in rank in toolbar
639			if (!toolbar->isReadOnly())
640			{
641				int new_rank = toolbar->getRankFromPosition(x,y);
642				toolbar->addCommand(command_id, new_rank);
643			}
644			
645			// Save the new toolbars configuration
646			gToolBarView->saveToolbars();
647		}
648		else
649		{
650			llwarns << "Command couldn't be found in command manager" << llendl;
651		}
652	}
653
654	resetDragTool(NULL);
655	return handled;
656}
657
658void LLToolBarView::resetDragTool(LLToolBarButton* toolbarButton)
659{
660	// Clear the saved command, toolbar and rank
661	gToolBarView->mDragStarted = false;
662	gToolBarView->mDragToolbarButton = toolbarButton;
663}
664
665void LLToolBarView::setToolBarsVisible(bool visible)
666{
667	mShowToolbars = visible;
668}
669
670bool LLToolBarView::isModified() const
671{
672	bool modified = false;
673
674	for (S32 i = TOOLBAR_FIRST; i <= TOOLBAR_LAST; i++)
675	{
676		modified |= mToolbars[i]->isModified();
677	}
678
679	return modified;
680}
681
682
683//
684// HACK to bring up destinations guide at startup
685//
686
687void handleLoginToolbarSetup()
688{
689	// Open the destinations guide by default on first login, per Rhett
690	if (gSavedPerAccountSettings.getBOOL("DisplayDestinationsOnInitialRun") || gAgent.isFirstLogin())
691	{
692		LLFloaterReg::showInstance("destinations");
693
694		gSavedPerAccountSettings.setBOOL("DisplayDestinationsOnInitialRun", FALSE);
695	}
696}
697