LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_params,
											  LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp )
	: LLScrollingPanel( panel_params ),
	  mParam(param),
	  mAllowModify(allow_modify),
	  mWearable(wearable)
{
	buildFromFile( "panel_scrolling_param.xml");

	// *HACK To avoid hard coding texture position, lets use border's position for texture. 
	LLViewBorder* left_border = getChild<LLViewBorder>("left_border");

	static LLUICachedControl<S32> slider_ctrl_height ("UISliderctrlHeight", 0);
	S32 pos_x = left_border->getRect().mLeft + left_border->getBorderWidth();
	S32 pos_y = left_border->getRect().mBottom + left_border->getBorderWidth();
	F32 min_weight = param->getMinWeight();
	F32 max_weight = param->getMaxWeight();

	mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), wearable,  min_weight, jointp);
	pos_x = getChild<LLViewBorder>("right_border")->getRect().mLeft + left_border->getBorderWidth();
	mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), wearable, max_weight, jointp );
	
	mHintMin->setAllowsUpdates( FALSE );
	mHintMax->setAllowsUpdates( FALSE );
	getChild<LLUICtrl>("param slider")->setValue(weightToPercent(param->getWeight()));

	std::string display_name = LLTrans::getString(param->getDisplayName());
	getChild<LLUICtrl>("param slider")->setLabelArg("[DESC]", display_name);
	getChildView("param slider")->setEnabled(mAllowModify);
	childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this);

	std::string min_name = LLTrans::getString(param->getMinDisplayName());
	std::string max_name = LLTrans::getString(param->getMaxDisplayName());
	getChild<LLUICtrl>("min param text")->setValue(min_name);
	getChild<LLUICtrl>("max param text")->setValue(max_name);

	LLButton* less = getChild<LLButton>("less");
	if (less)
	{
		less->setMouseDownCallback( LLScrollingPanelParam::onHintMinMouseDown, this );
		less->setMouseUpCallback( LLScrollingPanelParam::onHintMinMouseUp, this );
		less->setHeldDownCallback( LLScrollingPanelParam::onHintMinHeldDown, this );
		less->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
	}

	LLButton* more = getChild<LLButton>("more");
	if (more)
	{
		more->setMouseDownCallback( LLScrollingPanelParam::onHintMaxMouseDown, this );
		more->setMouseUpCallback( LLScrollingPanelParam::onHintMaxMouseUp, this );
		more->setHeldDownCallback( LLScrollingPanelParam::onHintMaxHeldDown, this );
		more->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
	}

	setVisible(FALSE);
	setBorderVisible( FALSE );
}
		NoticeText(const std::string& name, const LLRect& rect, const std::string& text = LLStringUtil::null, const LLFontGL* font = NULL) 
			: LLTextBox(name, rect, text, font)
		{
			setHAlign(LLFontGL::RIGHT);
			setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
			setBorderVisible(FALSE);
			setColor( gColors.getColor("GroupNotifyTextColor") );
			setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
		}
LLMediaCtrl::LLMediaCtrl( const Params& p) :
	LLPanel( p.name, p.rect, FALSE),
	LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()),
	mTextureDepthBytes( 4 ),
	mBorder(NULL),
	mFrequentUpdates( true ),
	mForceUpdate( false ),
	mHomePageUrl( "" ),
	mAlwaysRefresh( false ),
	mMediaSource( 0 ),
	mTakeFocusOnClick( p.focus_on_click ),
	mCurrentNavUrl( "about:blank" ),
	mStretchToFill( true ),
	mMaintainAspectRatio ( true ),
	mDecoupleTextureSize ( false ),
	mTextureWidth ( 1024 ),
	mTextureHeight ( 1024 ),
	mClearCache(false),
	mHomePageMimeType(p.initial_mime_type),
	mErrorPageURL(p.error_page_url),
	mTrusted(p.trusted_content),
	mHoverTextChanged(false),
	mContextMenu()
{
	{
		LLColor4 color = p.caret_color().get();
		setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
	}

	setHomePageUrl(p.start_url, p.initial_mime_type);
	
	setBorderVisible(p.border_visible);
	
	setDecoupleTextureSize(p.decouple_texture_size);
	
	setTextureSize(p.texture_width, p.texture_height);

	if(!getDecoupleTextureSize())
	{
		S32 screen_width = ll_round((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]);
		S32 screen_height = ll_round((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]);
			
		setTextureSize(screen_width, screen_height);
	}
	
	mMediaTextureID = getKey();
	
	// We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
	/*if(!mHomePageUrl.empty())
	{
		navigateHome();
	}*/
		

	//LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 );
}
LLScrollingPanelParam::LLScrollingPanelParam( const std::string& name,
											  LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, bool bVisualHint )
	: LLScrollingPanelParamBase( name, mesh, param, allow_modify, wearable, bVisualHint, LLRect( 0, PARAM_PANEL_HEIGHT, PARAM_PANEL_WIDTH, 0 )),
	  mLess(NULL),
	  mMore(NULL)
{

	if(bVisualHint)
	{
		S32 pos_x = 2 * LLPANEL_BORDER_WIDTH;
		S32 pos_y = 3 * LLPANEL_BORDER_WIDTH + SLIDERCTRL_HEIGHT;
		F32 min_weight = param->getMinWeight();
		F32 max_weight = param->getMaxWeight();

		mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, mWearable, min_weight);
		pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER;
		mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, mWearable, max_weight );

		mHintMin->setAllowsUpdates( FALSE );
		mHintMax->setAllowsUpdates( FALSE );

		// *TODO::translate
		std::string min_name = param->getMinDisplayName();
		std::string max_name = param->getMaxDisplayName();
		childSetValue("min param text", min_name);
		childSetValue("max param text", max_name);
		mLess = getChild<LLButton>("less");
		mLess->setMouseDownCallback( boost::bind(&LLScrollingPanelParam::onHintMouseDown, this, false) );
		mLess->setMouseUpCallback( boost::bind(&LLScrollingPanelParam::onHintMouseUp, this, false) );
		mLess->setHeldDownCallback( boost::bind(&LLScrollingPanelParam::onHintHeldDown, this, false) );
		mLess->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );

		mMore = getChild<LLButton>("more");
		mMore->setMouseDownCallback( boost::bind(&LLScrollingPanelParam::onHintMouseDown, this, true) );
		mMore->setMouseUpCallback( boost::bind(&LLScrollingPanelParam::onHintMouseUp, this, true) );
		mMore->setHeldDownCallback( boost::bind(&LLScrollingPanelParam::onHintHeldDown, this, true) );
		mMore->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
	}

	setVisible(FALSE);
	setBorderVisible( FALSE );
}
LLScrollingPanelParamBase::LLScrollingPanelParamBase( const std::string& name,
							LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, bool bVisualHint, LLRect rect )
	: LLScrollingPanel( name, rect ),
	mParam(param),
	mAllowModify(allow_modify),
	mWearable(wearable)
{
	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_scrolling_param.xml");
	//Set up the slider
	mSlider = getChild<LLSliderCtrl>("param slider");

	//Kill everything that isn't the slider...
	if(!bVisualHint)
	{
		child_list_t to_remove;
		child_list_t::const_iterator it;
		for (it = getChildList()->begin(); it != getChildList()->end(); it++)
		{
			if ((*it) != mSlider && (*it)->getName() != "panel border")
			{
				to_remove.push_back(*it);
			}
		}
		for (it = to_remove.begin(); it != to_remove.end(); it++)
		{
			removeChild(*it);
			delete (*it);
		}
		mSlider->translate(0,/*PARAM_HINT_HEIGHT*/128);
		reshape(getRect().getWidth(),getRect().getHeight()-128);
	}
	
	mSlider->setValue(weightToPercent(param->getWeight()));
	mSlider->setLabelArg("[DESC]", param->getDisplayName());
	mSlider->setEnabled(mAllowModify);
	mSlider->setCommitCallback(boost::bind(&LLScrollingPanelParamBase::onSliderMoved, this, _1));

	setVisible(FALSE);
	setBorderVisible( FALSE );
}
//---------------------------------------------------------------------------
// Singu Note: We could clean a lot of this up by creating derived classes for Notifications and NotificationTips.
LLNotifyBox::LLNotifyBox(LLNotificationPtr notification)
	:	LLPanel(notification->getName(), LLRect(), BORDER_NO),
		LLEventTimer(notification->getExpiration() == LLDate() 
			? LLDate(LLDate::now().secondsSinceEpoch() + (F64)gSavedSettings.getF32("NotifyTipDuration")) 
			: notification->getExpiration()),
		LLInstanceTracker<LLNotifyBox, LLUUID>(notification->getID()),
	  mNotification(notification),
	  mIsTip(notification->getType() == "notifytip"),
	  mAnimating(gNotifyBoxView->getChildCount() == 0), // Only animate first window
	  mNextBtn(NULL),
	  mNumOptions(0),
	  mNumButtons(0),
	  mAddedDefaultBtn(false),
	  mUserInputBox(NULL)
{
	std::string edit_text_name;
	std::string edit_text_contents;

	// setup paramaters
	const std::string& message(notification->getMessage());

	// initialize
	setFocusRoot(!mIsTip);

	// caution flag can be set explicitly by specifying it in the
	// notification payload, or it can be set implicitly if the
	// notify xml template specifies that it is a caution
	//
	// tip-style notification handle 'caution' differently -
	// they display the tip in a different color
	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;

	LLNotificationFormPtr form(notification->getForm());

	mNumOptions = form->getNumElements();
		  
	bool is_textbox = form->getElement("message").isDefined();

	bool layout_script_dialog(notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup");
	LLRect rect = mIsTip ? getNotifyTipRect(message)
		   		  		 : getNotifyRect(is_textbox ? 10 : mNumOptions, layout_script_dialog, mIsCaution);
	if ((form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE || form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE))
		rect.mBottom -= BTN_HEIGHT;
	setRect(rect);
	setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
	setBackgroundVisible(FALSE);
	setBackgroundOpaque(TRUE);

	const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
	const S32 BOTTOM = (S32)sFont->getLineHeight();
	S32 x = HPAD + HPAD;
	S32 y = TOP;

	auto icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+32, TOP-32), mIsTip ? "notify_tip_icon.tga" : mIsCaution ? "notify_caution_icon.tga" : "notify_box_icon.tga");

	icon->setMouseOpaque(FALSE);
	addChild(icon);

	x += HPAD + HPAD + 32;

	// add a caution textbox at the top of a caution notification
	if (mIsCaution && !mIsTip)
	{
		S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD;
		auto caution_box = new LLTextBox(
			std::string("caution_box"), 
			LLRect(x, y, getRect().getWidth() - 2, caution_height), 
			LLStringUtil::null, 
			sFont, 
			FALSE);

		caution_box->setFontStyle(LLFontGL::BOLD);
		caution_box->setColor(gColors.getColor("NotifyCautionWarnColor"));
		caution_box->setBackgroundColor(gColors.getColor("NotifyCautionBoxColor"));
		caution_box->setBorderVisible(FALSE);
		caution_box->setWrappedText(notification->getMessage());
		
		addChild(caution_box);

		// adjust the vertical position of the next control so that 
		// it appears below the caution textbox
		y = y - caution_height;
	}
	else
	{
		const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);

		// Tokenization on \n is handled by LLTextBox

		const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  // For script dialogs: add space for title.

		auto text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, LLStringUtil::null, sFont, FALSE, true);
		text->setWordWrap(TRUE);
		text->setMouseOpaque(TRUE);
		text->setBorderVisible(FALSE);
		text->setTakesNonScrollClicks(TRUE);
		text->setHideScrollbarForShortDocs(TRUE);
		text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually 
															// rendered under the text box, therefore we want 
															// the actual text box to be transparent

		auto text_color = gColors.getColor(mIsCaution && mIsTip ? "NotifyCautionWarnColor" : "NotifyTextColor");
		text->setReadOnlyFgColor(text_color); //sets caution text color for tip notifications
		if (!mIsCaution) // We could do some extra color math here to determine if bg's too close to link color, but let's just cross with the link color instead
			text->setLinkColor(new LLColor4(lerp(text_color, gSavedSettings.getColor4("HTMLLinkColor"), 0.4f)));
		text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard)
		text->appendText(message,false,false,nullptr,!layout_script_dialog); // Now we can set the text, since colors have been set.
		addChild(text);
	}

	if (mIsTip)
	{
		chat_notification(mNotification);
	}
	else
	{
		mNextBtn = new LLButton(std::string("next"),
						   LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD),
						   std::string("notify_next.png"),
						   std::string("notify_next.png"),
						   LLStringUtil::null,
						   boost::bind(&LLNotifyBox::moveToBack, this, true),
						   sFont);
		mNextBtn->setScaleImage(TRUE);
		mNextBtn->setToolTip(LLTrans::getString("next"));
		addChild(mNextBtn);

		for (S32 i = 0; i < mNumOptions; i++)
		{
			LLSD form_element = form->getElement(i);
			std::string element_type = form_element["type"].asString();
			if (element_type == "button") 
			{
				addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean(), layout_script_dialog);
			}
			else if (element_type == "input") 
			{
				edit_text_contents = form_element["value"].asString();
				edit_text_name = form_element["name"].asString();
			}
		}

		if (is_textbox)
		{
			S32 button_rows = layout_script_dialog ? 2 : 1;

			LLRect input_rect;
			input_rect.setOriginAndSize(x, BOTTOM_PAD + button_rows * (BTN_HEIGHT + VPAD),
										3 * 80 + 4 * HPAD, button_rows * (BTN_HEIGHT + VPAD) + BTN_HEIGHT);

			mUserInputBox = new LLTextEditor(edit_text_name, input_rect, 254,
											 edit_text_contents, sFont, FALSE);
			mUserInputBox->setBorderVisible(TRUE);
			mUserInputBox->setTakesNonScrollClicks(TRUE);
			mUserInputBox->setHideScrollbarForShortDocs(TRUE);
			mUserInputBox->setWordWrap(TRUE);
			mUserInputBox->setTabsToNextField(FALSE);
			mUserInputBox->setCommitOnFocusLost(FALSE);
			mUserInputBox->setAcceptCallingCardNames(FALSE);
			mUserInputBox->setHandleEditKeysDirectly(TRUE);

			addChild(mUserInputBox, -1);
		}
		else
		{
			setIsChrome(TRUE);
		}

		if (mNumButtons == 0)
		{
			addButton("OK", "OK", false, true, layout_script_dialog);
			mAddedDefaultBtn = true;
		}

		std::string check_title;
		if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
		{
			check_title = LLNotificationTemplates::instance().getGlobalString("skipnexttime");
		}
		else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
		{
			check_title = LLNotificationTemplates::instance().getGlobalString("alwayschoose");
		}
		if (!check_title.empty())
		{
			const LLFontGL* font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF);
			S32 line_height = llfloor(font->getLineHeight() + 0.99f);

			// Extend dialog for "check next time"
			S32 max_msg_width = getRect().getWidth() - HPAD * 9;
			S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16;
			max_msg_width = llmax(max_msg_width, check_width);

			S32 msg_x = (getRect().getWidth() - max_msg_width) / 2;

			LLRect check_rect;
			check_rect.setOriginAndSize(msg_x, BOTTOM_PAD + BTN_HEIGHT + VPAD*2 + (BTN_HEIGHT + VPAD) * (mNumButtons / 3),
				max_msg_width, line_height);

			LLCheckboxCtrl* check = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font,
				// Lambda abuse.
				[this](LLUICtrl* ctrl, const LLSD& param)
				{
						this->mNotification->setIgnored(ctrl->getValue());
				});
			check->setEnabledColor(LLUI::sColorsGroup->getColor(mIsCaution ? "AlertCautionTextColor" : "AlertTextColor"));
			if (mIsCaution)
			{
				check->setButtonColor(LLUI::sColorsGroup->getColor("ButtonCautionImageColor"));
			}
			addChild(check);
		}
		
		if (++sNotifyBoxCount <= 0)
			LL_WARNS() << "A notification was mishandled. sNotifyBoxCount = " << sNotifyBoxCount << LL_ENDL;
		// If this is the only notify box, don't show the next button
		else if (sNotifyBoxCount == 1 && mNextBtn)
			mNextBtn->setVisible(false);
	}
}
LLMediaCtrl::LLMediaCtrl( const Params& p) :
	LLPanel( p ),
	LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()),
	mTextureDepthBytes( 4 ),
	mBorder(NULL),
	mFrequentUpdates( true ),
	mForceUpdate( false ),
	mHomePageUrl( "" ),
	mAlwaysRefresh( false ),
	mMediaSource( 0 ),
	mTakeFocusOnClick( p.focus_on_click ),
	mCurrentNavUrl( "" ),
	mStretchToFill( true ),
	mMaintainAspectRatio ( true ),
	mDecoupleTextureSize ( false ),
	mTextureWidth ( 1024 ),
	mTextureHeight ( 1024 ),
	mClearCache(false),
	mHomePageMimeType(p.initial_mime_type),
	mErrorPageURL(p.error_page_url),
	mTrusted(p.trusted_content),
	mWindowShade(NULL),
	mHoverTextChanged(false),
	mContextMenu(NULL)
{
	{
		LLColor4 color = p.caret_color().get();
		setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
	}

	setHomePageUrl(p.start_url, p.initial_mime_type);
	
	setBorderVisible(p.border_visible);
	
	setDecoupleTextureSize(p.decouple_texture_size);
	
	setTextureSize(p.texture_width, p.texture_height);

	if(!getDecoupleTextureSize())
	{
		S32 screen_width = llround((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]);
		S32 screen_height = llround((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]);
			
		setTextureSize(screen_width, screen_height);
	}
	
	mMediaTextureID = getKey();
	
	// We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
	if(!mHomePageUrl.empty())
	{
		navigateHome();
	}
		
	LLWindowShade::Params params;
	params.name = "notification_shade";
	params.rect = getLocalRect();
	params.follows.flags = FOLLOWS_ALL;
	params.modal = true;

	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);

	addChild(mWindowShade);
}