void LLScrollingPanelParam::onHintHeldDown( bool max )
{
	LLVisualParamHint* hint = max ? mHintMax : mHintMin;
	LLViewerVisualParam* param = hint->getVisualParam();

	if(!mWearable || !param)
	{
		return;
	}

	F32 current_weight = mWearable->getVisualParamWeight( param->getID() );

	if (current_weight != hint->getVisualParamWeight() )
	{
		const F32 FULL_BLEND_TIME = 2.f;
		F32 elapsed_time = mMouseDownTimer.getElapsedTimeF32() - mLastHeldTime;
		mLastHeldTime += elapsed_time;

		F32 new_weight;
		if (current_weight > hint->getVisualParamWeight() )
		{
			new_weight = current_weight - (elapsed_time / FULL_BLEND_TIME);
		}
		else
		{
			new_weight = current_weight + (elapsed_time / FULL_BLEND_TIME);
		}

		// Make sure we're not taking the slider out of bounds
		// (this is where some simple UI limits are stored)
		F32 new_percent = weightToPercent(new_weight);
		LLSliderCtrl* slider = getChild<LLSliderCtrl>("param slider");
		if (slider)
		{
			if (slider->getMinValue() < new_percent
				&& new_percent < slider->getMaxValue())
			{
				mWearable->setVisualParamWeight(param->getID(), new_weight, FALSE);
				mWearable->writeToAvatar();
				gAgentAvatarp->updateVisualParams();

				slider->setValue( weightToPercent( new_weight ) );
			}
		}
	}
}
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 );
}
void LLScrollingPanelParam::onHintMouseUp( bool max )
{
	F32 elapsed_time = mMouseDownTimer.getElapsedTimeF32();

	if (isAgentAvatarValid())
	{
		LLVisualParamHint* hint			= max ? mHintMax : mHintMin;

		if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
		{
			LLViewerVisualParam* param = hint->getVisualParam();

			if(mWearable)
			{
				// step in direction
				F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
				F32 range = mHintMax->getVisualParamWeight() - mHintMin->getVisualParamWeight();
				//if min, range should be negative.
				if(!max)
					range *= -1.f;
				// step a fraction in the negative direction
				F32 new_weight = current_weight + (range / 10.f);
				F32 new_percent = weightToPercent(new_weight);
				LLSliderCtrl* slider = getChild<LLSliderCtrl>("param slider");
				if (slider)
				{
					if (slider->getMinValue() < new_percent
						&& new_percent < slider->getMaxValue())
					{
						mWearable->setVisualParamWeight(param->getID(), new_weight, FALSE);
						mWearable->writeToAvatar();
						slider->setValue( weightToPercent( new_weight ) );
					}
				}
			}
		}
	}

	LLVisualParamHint::requestHintUpdates( mHintMin, mHintMax );
}
void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify)
{
	if (!mWearable)
	{
		// not editing a wearable just now, no update necessary
		return;
	}

	F32 current_weight = mWearable->getVisualParamWeight(mParam->getID());
	mSlider->setValue(weightToPercent(current_weight));
	mAllowModify = allow_modify;
	mSlider->setEnabled(mAllowModify);
}
void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify)
{
	LLViewerVisualParam* param = mParam;
	
	if(!mWearable)
	{
		// not editing a wearable just now, no update necessary
		return;
	}

	F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
	childSetValue("param slider", weightToPercent( current_weight ) );
	mAllowModify = allow_modify;
	childSetEnabled("param slider", mAllowModify);
}
void LLScrollingPanelParam::updatePanel(BOOL allow_modify)
{
	LLViewerVisualParam* param = mHintMin->getVisualParam();

	if (!mWearable)
	{
		// not editing a wearable just now, no update necessary
		return;
	}
	F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
	getChild<LLUICtrl>("param slider")->setValue(weightToPercent( current_weight ) );
	mHintMin->requestUpdate( sUpdateDelayFrames++ );
	mHintMax->requestUpdate( sUpdateDelayFrames++ );

	mAllowModify = allow_modify;
	getChildView("param slider")->setEnabled(mAllowModify);
	getChildView("less")->setEnabled(mAllowModify);
	getChildView("more")->setEnabled(mAllowModify);
}
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 );
}