// static
void LLSliderCtrl::onSliderCommit( LLUICtrl* ctrl, const LLSD& userdata )
{
	LLSliderCtrl* self = dynamic_cast<LLSliderCtrl*>(ctrl->getParent());
	if (!self)
		return;

	BOOL success = FALSE;
	F32 saved_val = self->mValue;
	F32 new_val = self->mSlider->getValueF32();

	self->mValue = new_val;  // set the value temporarily so that the callback can retrieve it.
	if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) )
	{
		success = TRUE;
	}

	if( success )
	{
		self->onCommit();
	}
	else
	{
		if( self->mValue != saved_val )
		{
			self->setValue( saved_val );
		}
		self->reportInvalidData();		
	}
	self->updateText();
}
// static
void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
{
    LLSliderCtrl* self = (LLSliderCtrl*) userdata;
    llassert( caller == self->mEditor );

    BOOL success = FALSE;
    F32 val = self->mValue;
    F32 saved_val = self->mValue;

    std::string text = self->mEditor->getText();
    if( LLLineEditor::postvalidateFloat( text ) )
    {
        LLLocale locale(LLLocale::USER_LOCALE);
        val = (F32) atof( text.c_str() );
        if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
        {
            if( self->mValidateCallback )
            {
                self->setValue( val );  // set the value temporarily so that the callback can retrieve it.
                if( self->mValidateCallback( self, self->mCallbackUserData ) )
                {
                    success = TRUE;
                }
            }
            else
            {
                self->setValue( val );
                success = TRUE;
            }
        }
    }

    if( success )
    {
        self->onCommit();
    }
    else
    {
        if( self->getValueF32() != saved_val )
        {
            self->setValue( saved_val );
        }
        self->reportInvalidData();
    }
    self->updateText();
}
// static
void LLSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata )
{
	LLSliderCtrl* self = dynamic_cast<LLSliderCtrl*>(ctrl->getParent());
	if (!self)
		return;

	BOOL success = FALSE;
	F32 val = self->mValue;
	F32 saved_val = self->mValue;

	std::string text = self->mEditor->getText();
	if( LLLineEditor::postvalidateFloat( text ) )
	{
		LLLocale locale(LLLocale::USER_LOCALE);
		val = (F32) atof( text.c_str() );
		if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
		{
			self->setValue( val );  // set the value temporarily so that the callback can retrieve it.
			if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) )
			{
				success = TRUE;
			}
		}
	}

	if( success )
	{
		self->onCommit();
	}
	else
	{
		if( self->getValueF32() != saved_val )
		{
			self->setValue( saved_val );
		}
		self->reportInvalidData();		
	}
	self->updateText();
}
// static
void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
{
    LLSliderCtrl* self = (LLSliderCtrl*) userdata;
    llassert( caller == self->mSlider );

    BOOL success = FALSE;
    F32 saved_val = self->mValue;
    F32 new_val = self->mSlider->getValueF32();

    if( self->mValidateCallback )
    {
        self->mValue = new_val;  // set the value temporarily so that the callback can retrieve it.
        if( self->mValidateCallback( self, self->mCallbackUserData ) )
        {
            success = TRUE;
        }
    }
    else
    {
        self->mValue = new_val;
        success = TRUE;
    }

    if( success )
    {
        self->onCommit();
    }
    else
    {
        if( self->mValue != saved_val )
        {
            self->setValue( saved_val );
        }
        self->reportInvalidData();
    }
    self->updateText();
}
LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
    std::string name("slider");
    node->getAttributeString("name", name);

    std::string label;
    node->getAttributeString("label", label);

    LLRect rect;
    createRect(node, rect, parent, LLRect());

    LLFontGL* font = LLView::selectFont(node);

    // HACK: Font might not be specified.
    if (!font)
    {
        font = LLFontGL::getFontSansSerifSmall();
    }

    S32 label_width = 0;
    node->getAttributeS32("label_width", label_width);

    BOOL show_text = TRUE;
    node->getAttributeBOOL("show_text", show_text);

    BOOL can_edit_text = FALSE;
    node->getAttributeBOOL("can_edit_text", can_edit_text);

    BOOL volume = FALSE;
    node->getAttributeBOOL("volume", volume);

    F32 initial_value = 0.f;
    node->getAttributeF32("initial_val", initial_value);

    F32 min_value = 0.f;
    node->getAttributeF32("min_val", min_value);

    F32 max_value = 1.f;
    node->getAttributeF32("max_val", max_value);

    F32 increment = 0.1f;
    node->getAttributeF32("increment", increment);

    U32 precision = 3;
    node->getAttributeU32("decimal_digits", precision);

    S32 text_left = 0;
    if (show_text)
    {
        // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
        if ( max_value )
            text_left = font->getWidth(std::string("0")) * ( static_cast < S32 > ( log10  ( max_value ) ) + precision + 1 );

        if ( increment < 1.0f )
            text_left += font->getWidth(std::string("."));	// (mostly) take account of decimal point in value

        if ( min_value < 0.0f || max_value < 0.0f )
            text_left += font->getWidth(std::string("-"));	// (mostly) take account of minus sign

        // padding to make things look nicer
        text_left += 8;
    }

    LLUICtrlCallback callback = NULL;

    if (label.empty())
    {
        label.assign(node->getTextContents());
    }

    LLSliderCtrl* slider = new LLSliderCtrl(name,
                                            rect,
                                            label,
                                            font,
                                            label_width,
                                            rect.getWidth() - text_left,
                                            show_text,
                                            can_edit_text,
                                            volume,
                                            callback,
                                            NULL,
                                            initial_value,
                                            min_value,
                                            max_value,
                                            increment);

    slider->setPrecision(precision);

    slider->initFromXML(node, parent);

    slider->updateText();

    return slider;
}