void LLPanelLogin::setLoginHistory(LLSavedLogins const& login_history)
{
	sInstance->mLoginHistoryData = login_history;

	LLComboBox* login_combo = sInstance->getChild<LLComboBox>("first_name_combo");
	llassert(login_combo);
	login_combo->clear();

	LLSavedLoginsList const& saved_login_entries(login_history.getEntries());
	for (LLSavedLoginsList::const_reverse_iterator i = saved_login_entries.rbegin();
	     i != saved_login_entries.rend(); ++i)
	{
		LLSD e = i->asLLSD();
		if (e.isMap()) login_combo->add(i->getDisplayString(), e);
	}
}
//---------------------------------------------------------------------------
// Public methods
//---------------------------------------------------------------------------
LLPanelLogin::LLPanelLogin(const LLRect& rect)
:	LLPanel(std::string("panel_login"), rect, FALSE),		// not bordered
	mLogoImage(LLUI::getUIImage("startup_logo.j2c"))
{
	setFocusRoot(TRUE);

	setBackgroundVisible(FALSE);
	setBackgroundOpaque(TRUE);

	LLPanelLogin::sInstance = this;

	// add to front so we are the bottom-most child
	gViewerWindow->getRootView()->addChildInBack(this);

	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_login.xml");

	reshape(rect.getWidth(), rect.getHeight());

	LLComboBox* username_combo(getChild<LLComboBox>("username_combo"));
	username_combo->setCommitCallback(boost::bind(LLPanelLogin::onSelectLoginEntry, _1, this));
	username_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLoginComboLostFocus, this, username_combo));
	username_combo->setPrevalidate(LLLineEditor::prevalidatePrintableNotPipe);
	username_combo->setSuppressTentative(true);
	username_combo->setSuppressAutoComplete(true);

	childSetCommitCallback("remember_name_check", onNameCheckChanged);

	LLLineEditor* password_edit(getChild<LLLineEditor>("password_edit"));
	password_edit->setKeystrokeCallback(onPassKey);
	// STEAM-14: When user presses Enter with this field in focus, initiate login
	password_edit->setCommitCallback(mungePassword, this);
	password_edit->setDrawAsterixes(TRUE);

	getChild<LLUICtrl>("remove_login")->setCommitCallback(boost::bind(&LLPanelLogin::confirmDelete, this));

	// change z sort of clickable text to be behind buttons
	sendChildToBack(getChildView("channel_text"));
	sendChildToBack(getChildView("forgot_password_text"));

	//llinfos << " url history: " << LLSDOStreamer<LLSDXMLFormatter>(LLURLHistory::getURLHistory("regionuri")) << llendl;

	LLComboBox* location_combo = getChild<LLComboBox>("start_location_combo");
	updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
	location_combo->setAllowTextEntry(TRUE, 128, FALSE);
	location_combo->setFocusLostCallback( boost::bind(&LLPanelLogin::onLocationSLURL, this) );
	
	LLComboBox *server_choice_combo = getChild<LLComboBox>("grids_combo");
	server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectGrid, _1));
	server_choice_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onSelectGrid, server_choice_combo));
	
	// Load all of the grids, sorted, and then add a bar and the current grid at the top
	updateGridCombo();

	LLSLURL start_slurl(LLStartUp::getStartSLURL());
	if ( !start_slurl.isSpatial() ) // has a start been established by the command line or NextLoginLocation ? 
	{
		// no, so get the preference setting
		std::string defaultStartLocation = gSavedSettings.getString("LoginLocation");
		LL_INFOS("AppInit")<<"default LoginLocation '"<<defaultStartLocation<<"'"<<LL_ENDL;
		LLSLURL defaultStart(defaultStartLocation);
		if ( defaultStart.isSpatial() )
		{
			LLStartUp::setStartSLURL(defaultStart);	// calls onUpdateStartSLURL
		}
		else
		{
			LL_INFOS("AppInit")<<"no valid LoginLocation, using home"<<LL_ENDL;
			LLSLURL homeStart(LLSLURL::SIM_LOCATION_HOME);
			LLStartUp::setStartSLURL(homeStart); // calls onUpdateStartSLURL
		}
	}
	else
	{
		LLPanelLogin::onUpdateStartSLURL(start_slurl); // updates grid if needed
	}


	// Also set default button for subpanels, otherwise hitting enter in text entry fields won't login
	{
		LLButton* connect_btn(findChild<LLButton>("connect_btn"));
		connect_btn->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
		setDefaultBtn(connect_btn);
		findChild<LLPanel>("name_panel")->setDefaultBtn(connect_btn);
		findChild<LLPanel>("password_panel")->setDefaultBtn(connect_btn);
		findChild<LLPanel>("grids_panel")->setDefaultBtn(connect_btn);
		findChild<LLPanel>("location_panel")->setDefaultBtn(connect_btn);
		findChild<LLPanel>("login_html")->setDefaultBtn(connect_btn);
	}

	childSetAction("grids_btn", onClickGrids, this);

	std::string channel = gVersionChannel;

	std::string version = llformat("%d.%d.%d (%d)",
		gVersionMajor,
		gVersionMinor,
		gVersionPatch,
		gVersionBuild );
	LLTextBox* channel_text = getChild<LLTextBox>("channel_text");
	channel_text->setTextArg("[CHANNEL]", channel); // though not displayed
	channel_text->setTextArg("[VERSION]", version);
	channel_text->setClickedCallback(boost::bind(&LLPanelLogin::onClickVersion,(void*)NULL));
	
	LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");
	forgot_password_text->setClickedCallback(boost::bind(&onClickForgotPassword));

	
	LLTextBox* create_new_account_text = getChild<LLTextBox>("create_new_account_text");
	create_new_account_text->setClickedCallback(boost::bind(&onClickNewAccount));

	// get the web browser control
	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
	web_browser->addObserver(this);
	web_browser->setBackgroundColor(LLColor4::black);

	reshapeBrowser();

	refreshLoginPage();

	gHippoGridManager->setCurrentGridChangeCallback(boost::bind(&LLPanelLogin::onCurGridChange,this,_1,_2));

	// Load login history
	std::string login_hist_filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "saved_logins_sg2.xml");
	mLoginHistoryData = LLSavedLogins::loadFile(login_hist_filepath);

	const LLSavedLoginsList& saved_login_entries(mLoginHistoryData.getEntries());
	for (LLSavedLoginsList::const_reverse_iterator i = saved_login_entries.rbegin();
	     i != saved_login_entries.rend(); ++i)
	{
		LLSD e = i->asLLSD();
		if (e.isMap() && gHippoGridManager->getGrid(i->getGrid()))
			username_combo->add(getDisplayString(*i), e);
	}

	if (saved_login_entries.size() > 0)
	{
		setFields(*saved_login_entries.rbegin());
	}
}
// static
void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
{
	// *NOTE: The parameters for this method are ignored.

	// This function is only called by one thread, so we can use a static here.
	static bool looping;
	if (looping) return;
	looping = true;

	// LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
	// calls this method.

	// The user twiddled with the grid choice ui.
	// apply the selection to the grid setting.
	std::string grid_name;
	S32 grid_index;

	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
	LLSD combo_val = combo->getValue();

	if (LLSD::TypeInteger == combo_val.type())
	{
		grid_index = combo->getValue().asInteger();
		grid_name = combo->getSimple();
	}
	else
	{
		// no valid selection, return other
		grid_index = (S32)GRID_INFO_OTHER;
		grid_name = combo_val.asString();
	}

	// This new selection will override preset uris
	// from the command line.
	LLViewerLogin* vl = LLViewerLogin::getInstance();

	if(grid_index != GRID_INFO_OTHER)
	{
		vl->setGridChoice((EGridInfo)grid_index);
	}
	else
	{
		vl->setGridChoice(grid_name);
	}

	// Find a saved login entry that uses this grid, if any.
	bool found = false;
	LLSavedLoginsList const& entries = sInstance->mLoginHistoryData.getEntries();
	for (LLSavedLoginsList::const_reverse_iterator i = entries.rbegin(); i != entries.rend(); ++i)
	{
		if (!i->asLLSD().isMap())
		{
			continue;
		}
		if (i->getGridName() == grid_name)
		{
		  	if (!vl->nameEditted())
			{
				// Change the other fields to match this grid.
				LLPanelLogin::setFields(*i, false);
			}
			else	// Probably creating a new account.
			{
				// Likely the current password is for a different grid.
				clearPassword();
			}
			found = true;
			break;
		}
	}
	if (!found)
	{
		clearPassword();

		// If the grid_name starts with 'http[s]://' then
		// we have to assume it's a new loginuri, set
		// on the commandline.
		if (grid_name.substr(0, 4) == "http")
		{
			// Use it as login uri.
			vl->setGridURI(grid_name);
			// And set the login page if it was given.
			std::string loginPage = gSavedSettings.getString("LoginPage");
			std::string helperURI = gSavedSettings.getString("CmdLineHelperURI");
			if (!loginPage.empty()) vl->setLoginPageURI(loginPage);
			if (!helperURI.empty()) vl->setHelperURI(helperURI);
		}
	}

	// grid changed so show new splash screen (possibly)
	loadLoginPage();

	looping = false;
}