LLXMLNodePtr LLJoystick::getXML(bool save_children) const
{
	LLXMLNodePtr node = LLUICtrl::getXML();

	node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(getHAlign()));
	node->createChild("quadrant", TRUE)->setStringValue(nameFromQuadrant(mInitialQuadrant));

	addImageAttributeToXML(node,getImageUnselectedName(),getImageUnselectedID(),std::string("image_unselected"));
	addImageAttributeToXML(node,getImageSelectedName(),getImageSelectedID(),std::string("image_selected"));
	
	node->createChild("scale_image", TRUE)->setBoolValue(getScaleImage());

	return node;
}
RRect RLineCache::flush(class IRichCompositor* compositor)
{
	RRect line_rect;

	// no element yet, need not flush!
	element_list_t* line = getCachedElements();
	if ( line->size() == 0 )
		return line_rect;

	// line mark
	std::vector<element_list_t::iterator> line_marks;
	std::vector<short> line_widths;

	RRect zone = compositor->getMetricsState()->zone;
	bool wrapline = m_rWrapLine;

	// line width auto growth
	if ( zone.size.w == 0 )
		wrapline = false;
	
	RMetricsState* mstate = compositor->getMetricsState();

	RPos pen;
	RRect temp_linerect;
	short base_line_pos_y = 0;
	element_list_t::iterator inner_start_it = line->begin();
	line_marks.push_back(line->begin()); // push first line start
	for ( element_list_t::iterator it = line->begin(); it != line->end(); it++ )
	{
		RMetrics* metrics = (*it)->getMetrics();

		// prev composit event
		(*it)->onCachedCompositBegin(this, pen);

		// calculate baseline offset
		short baseline_correct = 0;
		if ( (*it)->needBaselineCorrect() )
		{
			baseline_correct = m_rBaselinePos;
		}

		// first element
		if ( pen.x == 0 )
		{
			pen.x -= metrics->rect.min_x();
		}
		
		// set position
		(*it)->setLocalPositionX(pen.x);
		(*it)->setLocalPositionY(pen.y + baseline_correct);

		RRect rect = metrics->rect;
		rect.pos.x += pen.x;
		rect.pos.y += baseline_correct;
		temp_linerect.extend(rect);

		// process wrapline
		element_list_t::iterator next_it = it + 1;
		if ( next_it == line->end() ||	// last element
			(*next_it)->isNewlineBefore() || // line-break before next element
			(*it)->isNewlineFollow() ||	// line-break after this element
			( wrapline && pen.x != 0		// wrap line
			&& pen.x + metrics->advance.x + (*next_it)->getMetrics()->rect.pos.x + (*next_it)->getMetrics()->rect.size.w + getPadding()*2 > zone.size.w 
			&& (*next_it)->canLinewrap() ) )
		{
			// correct out of bound correct
			short y2correct = -temp_linerect.max_y();

			for ( element_list_t::iterator inner_it = inner_start_it; inner_it != next_it; inner_it++ )
			{
				RPos pos = (*inner_it)->getLocalPosition();
				(*inner_it)->setLocalPositionY(pos.y + y2correct);
				(*inner_it)->setLocalPositionX(pos.x /*+ x2correct*/);
			}

			temp_linerect.pos.y = pen.y;
			line_rect.extend(temp_linerect);

			pen.y -= (temp_linerect.size.h + getSpacing());
			pen.x = 0;

			// push next line start
			line_marks.push_back(next_it);
			line_widths.push_back(temp_linerect.size.w);

			inner_start_it = next_it;
			temp_linerect = RRect();
		}
		else
		{
			pen.x += metrics->advance.x;
		}
		
		// post composit event
		(*it)->onCachedCompositEnd(this, pen);
	}

	short align_correct_x = 0;
	size_t line_mark_idx = 0;
	if ( getHAlign() == e_align_left )
		line_rect.size.w += getPadding() * 2;
	else
		line_rect.size.w = RMAX(zone.size.w, line_rect.size.w + getPadding() * 2); // auto rect
	for ( element_list_t::iterator it = line->begin(); it != line->end(); it++ )
	{
		// prev composit event
		(*it)->onCachedCompositBegin(this, pen);

		if ( it == line_marks[line_mark_idx] )
		{
			short lwidth = line_widths[line_mark_idx];

			// x correct
			switch ( getHAlign() )
			{
			case e_align_left:
				align_correct_x = getPadding();
				break;
			case e_align_center:
				align_correct_x = ( line_rect.size.w - lwidth ) / 2;
				break;
			case e_align_right:
				align_correct_x = line_rect.size.w - lwidth - getPadding();
				break;
			}

			line_mark_idx++; // until next line
		}

		RPos pos = (*it)->getLocalPosition();
		(*it)->setLocalPositionX(mstate->pen_x + pos.x + align_correct_x);
		(*it)->setLocalPositionY(mstate->pen_y + pos.y);

		// post composit event
		(*it)->onCachedCompositEnd(this, pen);
	}

	line_rect.pos.y = mstate->pen_y;

	// advance pen position
	mstate->pen_y -= (line_rect.size.h + getSpacing());
	mstate->pen_x = 0;
	
	clear();

	return line_rect;
}