/*************************************************************************
	Draw the list box item in its current state.
*************************************************************************/
void ListboxTextItem::draw(std::vector<GeometryBuffer*>& geometry_buffers, const Rectf& targetRect,
                           float alpha, const Rectf* clipper) const
{
    if (d_selected && d_selectBrush != 0)
    {
        d_selectBrush->render(geometry_buffers, targetRect, clipper, true,
                            d_selectCols, alpha);
    }

    const Font* font = getFont();

    if (!font)
        return;

    glm::vec2 draw_pos(targetRect.getPositionGLM());

    draw_pos.y += CoordConverter::alignToPixels(
        (font->getLineSpacing() - font->getFontHeight()) * 0.5f);

    if (!d_renderedStringValid)
        parseTextString();

    const ColourRect final_colours(ColourRect(0xFFFFFFFF));

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        d_renderedString.draw(d_owner, i, geometry_buffers, draw_pos, &final_colours, clipper, 0.0f);
        draw_pos.y += d_renderedString.getPixelSize(d_owner, i).d_height;
    }
}
//------------------------------------------------------------------------------//
void InventoryReceiver::populateGeometryBuffer()
{
    if (!isUserStringDefined("BlockImage"))
        return;

    const Image* img = PropertyHelper<Image*>::fromString(getUserString("BlockImage"));

    if (!img)
        return;

    const Sizef square_size(squarePixelSize());

    for (int y = 0; y < d_content.height(); ++y)
    {
        for (int x = 0; x < d_content.width(); ++x)
        {
            argb_t colour = 0xFFFFFFFF;
            if (d_content.elementAtLocation(x, y))
                colour = 0xFF0000FF;

            img->render(*d_geometry,
                        Vector2f(x * square_size.d_width + 1, y * square_size.d_height + 1),
                        Sizef(square_size.d_width - 2, square_size.d_height - 2), 0,
                        ColourRect(colour));
        }
    }
}
		void EffectColorLevel::set(PropertyReceiver* receiver, const String& value)
		{
			int nIndex = 0;
			argb_t topLeft = 0xFF000000, topRight = 0xFF000000, bottomLeft = 0xFF000000, bottomRight = 0xFF000000;
			sscanf(value.c_str(), "index:%d tl:%8X tr:%8X bl:%8X br:%8X", &nIndex, &topLeft, &topRight, &bottomLeft, &bottomRight );
			static_cast<FalagardSuperProgress*>(receiver)->setEffectColorLevel( nIndex, ColourRect( topLeft, topRight, bottomLeft, bottomRight ) );
		}
//------------------------------------------------------------------------------//
void InventoryItem::populateGeometryBuffer()
{
    if (!isUserStringDefined("BlockImage"))
        return;

    const Image* img = PropertyHelper<Image*>::fromString(getUserString("BlockImage"));

    if (!img)
        return;

    const Sizef square_size(squarePixelSize());

    argb_t colour = 0xFF00FF00;

    if (d_dragging && !currentDropTargetIsValid())
        colour = 0xFFFF0000;

    for (int y = 0; y < d_content.height(); ++y)
    {
        for (int x = 0; x < d_content.width(); ++x)
        {
            if (d_content.elementAtLocation(x, y))
            {
                img->render(d_geometryBuffers,
                            glm::vec2(x * square_size.d_width + 1, y * square_size.d_height + 1),
                            Sizef(square_size.d_width - 2, square_size.d_height - 2), 0, false,
                            ColourRect(colour));
            }
        }
    }
}
/*************************************************************************
	Draw the list box item in its current state.
*************************************************************************/
void ListboxTextItem::draw(GeometryBuffer& buffer, const Rect& targetRect,
                           float alpha, const Rect* clipper) const
{
    if (d_selected && d_selectBrush != 0)
        d_selectBrush->draw(buffer, targetRect, clipper,
                            getModulateAlphaColourRect(d_selectCols, alpha));

    Font* font = getFont();

    if (!font)
        return;

    Vector2 draw_pos(targetRect.getPosition());

    draw_pos.d_y += PixelAligned(
        (font->getLineSpacing() - font->getFontHeight()) * 0.5f);

    if (!d_renderedStringValid)
        parseTextString();

    const ColourRect final_colours(
        getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha));

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        d_renderedString.draw(i, buffer, draw_pos, &final_colours, clipper, 0.0f);
        draw_pos.d_y += d_renderedString.getPixelSize(i).d_height;
    }
}
//----------------------------------------------------------------------------//
void FormattedListboxTextItem::draw(GeometryBuffer& buffer,
                                    const Rect& targetRect,
                                    float alpha, const Rect* clipper) const
{
    // reparse text if we need to.
    if (!d_renderedStringValid)
        parseTextString();

    // create formatter if needed
    if (!d_formattedRenderedString)
        setupStringFormatter();

    // get size of render area from target window, to see if we need to reformat
    // NB: We do not use targetRect, since it may not represent the same area.
    const Size area_sz(static_cast<const Listbox*>(d_owner)->
        getListRenderArea().getSize());
    if (area_sz != d_formattingAreaSize)
    {
        d_formattedRenderedString->format(area_sz);
        d_formattingAreaSize = area_sz;
    }

    // draw selection imagery
    if (d_selected && d_selectBrush != 0)
        d_selectBrush->draw(buffer, targetRect, clipper,
                            getModulateAlphaColourRect(d_selectCols, alpha));

    // factor the window alpha into our colours.
    const ColourRect final_colours(
        getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha));

    // draw the formatted text
    d_formattedRenderedString->draw(buffer, targetRect.getPosition(),
                                    &final_colours, clipper);
}
/*************************************************************************
	Return a ColourRect object describing the colours in 'cols' after
	having their alpha component modulated by the value 'alpha'.
*************************************************************************/
ColourRect ListboxItem::getModulateAlphaColourRect(const ColourRect& cols, float alpha) const
{
	return ColourRect
		(
			calculateModulatedAlphaColour(cols.d_top_left, alpha),
			calculateModulatedAlphaColour(cols.d_top_right, alpha),
			calculateModulatedAlphaColour(cols.d_bottom_left, alpha),
			calculateModulatedAlphaColour(cols.d_bottom_right, alpha)
		);
}
void ListboxImageItem::draw(RenderCache& cache,const Rect& targetRect, float zBase, float alpha, const Rect* clipper) const
{
    if (d_selected && d_selectBrush != 0)
    {
        cache.cacheImage(*d_selectBrush, targetRect, zBase, getModulateAlphaColourRect(d_selectCols, alpha), clipper);
    }

	if (d_image != NULL)
	{
		cache.cacheImage(*d_image, targetRect, zBase, ColourRect(colour(1,1,1,alpha)), clipper);
	}
}
/*************************************************************************
    Draw the tree item in its current state.
*************************************************************************/
void TreeItem::draw(GeometryBuffer& buffer, const Rect &targetRect,
                    float alpha, const Rect *clipper) const
{
    Rect finalRect(targetRect);

    if (d_iconImage != 0)
    {
        Rect finalPos(finalRect);
        finalPos.setWidth(targetRect.getHeight());
        finalPos.setHeight(targetRect.getHeight());
        d_iconImage->draw(buffer, finalPos, clipper,
                          ColourRect(colour(1,1,1,alpha)));
        finalRect.d_left += targetRect.getHeight();
    }

    if (d_selected && d_selectBrush != 0)
        d_selectBrush->draw(buffer, finalRect, clipper,
                            getModulateAlphaColourRect(d_selectCols, alpha));

    Font* font = getFont();

    if (!font)
        return;

    Vector2 draw_pos(finalRect.getPosition());
    draw_pos.d_y -= (font->getLineSpacing() - font->getBaseline()) * 0.5f;

    if (!d_renderedStringValid)
        parseTextString();

    const ColourRect final_colours(
        getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha));

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        d_renderedString.draw(i, buffer, draw_pos, &final_colours, clipper, 0.0f);
        draw_pos.d_y += d_renderedString.getPixelSize(i).d_height;
    }
}
//----------------------------------------------------------------------------//
void ColourPicker::setColour(const Colour& newColour)
{
    d_selectedColour = newColour;

    WindowEventArgs e(this);
    fireEvent(EventAcceptedColour, e, EventNamespace);

    Colour selectedColourNoAlpha = d_selectedColour;
    selectedColourNoAlpha.setAlpha(1.0f);
    String colourRectString(PropertyHelper<ColourRect>::toString(
                                ColourRect(selectedColourNoAlpha)));

    this->setProperty("Colour", colourRectString);
}
//----------------------------------------------------------------------------//
void FormattedListboxTextItem::draw(GeometryBuffer& buffer,
	const Rect& targetRect,
	float alpha, const Rect* clipper) const
{
	updateString();

	// draw selection imagery
	if (d_selected && d_selectBrush != 0)
		d_selectBrush->draw(buffer, targetRect, clipper,
		getModulateAlphaColourRect(d_selectCols, alpha));

	// factor the window alpha into our colours.
	const ColourRect final_colours(
		getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha));

	// draw the formatted text
	d_formattedRenderedString->draw(buffer, targetRect.getPosition(),
		&final_colours, clipper);
}
PropertyHelper<ColourRect>::return_type
PropertyHelper<ColourRect>::fromString(const String& str)
{
    ColourRect val(Colour(0xFF000000));

    if (str.empty())
         return val;

    std::stringstream& sstream = SharedStringstream::GetPreparedStream(str);

    if (str.length() == 8)
    {
        CEGUI::Colour colourForEntireRect(0xFF000000);

        sstream >> colourForEntireRect;
        if (sstream.fail())
            throwParsingException(getDataTypeName(), str);

        val = ColourRect(colourForEntireRect);

        return val;
    }
//----------------------------------------------------------------------------//
void RenderedStringWidgetComponent::draw(const Window* ref_wnd,
                                         GeometryBuffer& buffer,
                                         const Vector2f& position,
                                         const CEGUI::ColourRect* /*mod_colours*/,
                                         const Rectf* clip_rect,
                                         const float vertical_space,
                                         const float /*space_extra*/) const
{
    Window* const window = getEffectiveWindow(ref_wnd);

    if (!window)
        return;

    // HACK: re-adjust for inner-rect of parent
    float x_adj = 0, y_adj = 0;
    Window* parent = window->getParent();
    
    if (parent)
    {
        const Rectf& outer(parent->getUnclippedOuterRect().get());
        const Rectf& inner(parent->getUnclippedInnerRect().get());
        x_adj = inner.d_min.d_x - outer.d_min.d_x;
        y_adj = inner.d_min.d_y - outer.d_min.d_y;
    }
    // HACK: re-adjust for inner-rect of parent (Ends)

    Vector2f final_pos(position);
    // handle formatting options
    switch (d_verticalFormatting)
    {
    case VF_BOTTOM_ALIGNED:
        final_pos.d_y += vertical_space - getPixelSize(ref_wnd).d_height;
        break;

    case VF_STRETCHED:
        Logger::getSingleton().logEvent("RenderedStringWidgetComponent::draw: "
            "VF_STRETCHED specified but is unsupported for Widget types; "
            "defaulting to VF_CENTRE_ALIGNED instead.");
        
        // intentional fall-through.
        
    case VF_CENTRE_ALIGNED:
        final_pos.d_y += (vertical_space - getPixelSize(ref_wnd).d_height) / 2 ;
        break;


    case VF_TOP_ALIGNED:
        // nothing additional to do for this formatting option.
        break;

    default:
        CEGUI_THROW(InvalidRequestException(
                "unknown VerticalFormatting option specified."));
    }

    // render the selection if needed
    if (d_selectionImage && d_selected)
    {
        const Rectf select_area(position, getPixelSize(ref_wnd));
        d_selectionImage->render(buffer, select_area, clip_rect, ColourRect(0xFF002FFF));
    }

    // we do not actually draw the widget, we just move it into position.
    const UVector2 wpos(UDim(0, final_pos.d_x + d_padding.d_min.d_x - x_adj),
                        UDim(0, final_pos.d_y + d_padding.d_min.d_y - y_adj));

    window->setPosition(wpos);
}
//----------------------------------------------------------------------------//
void RenderedStringImageComponent::draw(const Window* ref_wnd,
                                        std::vector<GeometryBuffer*>& geometry_buffers,
                                        const glm::vec2& position,
                                        const ColourRect* mod_colours,
                                        const Rectf* clip_rect,
                                        const float vertical_space,
                                        const float /*space_extra*/) const
{
    if (!d_image)
        return;

    Rectf dest(position.x, position.y, 0, 0);
    float y_scale = 1.0f;

    // handle formatting options
    switch (d_verticalFormatting)
    {
    case VF_BOTTOM_ALIGNED:
        dest.d_min.y += vertical_space - getPixelSize(ref_wnd).d_height;
        break;

    case VF_CENTRE_ALIGNED:
        dest.d_min.y += (vertical_space - getPixelSize(ref_wnd).d_height) / 2 ;
        break;

    case VF_STRETCHED:
        y_scale = vertical_space / getPixelSize(ref_wnd).d_height;
        break;

    case VF_TOP_ALIGNED:
        // nothing additional to do for this formatting option.
        break;

    default:
        throw InvalidRequestException(
            "unknown VerticalFormatting option specified.");
    }

    Sizef sz(d_image->getRenderedSize());
    if (d_size.d_width != 0.0)
        sz.d_width = d_size.d_width;
    if (d_size.d_height != 0.0)
        sz.d_height = d_size.d_height;
    
    sz.d_height *= y_scale;
    dest.setSize(sz);

    // apply padding to position
    dest.offset(d_padding.getPosition());

    // render the selection if needed
    if (d_selectionImage && d_selected)
    {
        const Rectf select_area(position, getPixelSize(ref_wnd));
        d_selectionImage->render(geometry_buffers, select_area, clip_rect, true, ColourRect(0xFF002FFF));
    }

    // apply modulative colours if needed.
    ColourRect final_cols(d_colours);
    if (mod_colours)
        final_cols *= *mod_colours;

    // draw the image. 
    d_image->render(geometry_buffers, dest, clip_rect, true, final_cols);
}
//----------------------------------------------------------------------------//
void RenderedStringTextComponent::draw(const Window* ref_wnd,
                                       GeometryBuffer& buffer,
                                       const Vector2f& position,
                                       const ColourRect* mod_colours,
                                       const Rectf* clip_rect,
                                       const float vertical_space,
                                       const float space_extra) const
{
    const Font* fnt = getEffectiveFont(ref_wnd); 

    if (!fnt)
        return;

    Vector2f final_pos(position);
    float y_scale = 1.0f;

    // handle formatting options
    switch (d_verticalFormatting)
    {
    case VF_BOTTOM_ALIGNED:
        final_pos.d_y += vertical_space - getPixelSize(ref_wnd).d_height;
        break;

    case VF_CENTRE_ALIGNED:
        final_pos.d_y += (vertical_space - getPixelSize(ref_wnd).d_height) / 2 ;
        break;

    case VF_STRETCHED:
        y_scale = vertical_space / getPixelSize(ref_wnd).d_height;
        break;

    case VF_TOP_ALIGNED:
        // nothing additional to do for this formatting option.
        break;

    default:
        CEGUI_THROW(InvalidRequestException(
            "unknown VerticalFormatting option specified."));
    }

    // apply padding to position:
    final_pos += d_padding.getPosition();

    // apply modulative colours if needed.
    ColourRect final_cols(d_colours);
    if (mod_colours)
        final_cols *= *mod_colours;

    // render selection
    if (d_selectionImage && d_selectionLength)
    {
        float sel_start_extent = 0, sel_end_extent = 0;

        if (d_selectionStart > 0)
            sel_start_extent = fnt->getTextExtent(d_text.substr(0, d_selectionStart));

        sel_end_extent = fnt->getTextExtent(d_text.substr(0, d_selectionStart + d_selectionLength));

        Rectf sel_rect(position.d_x + sel_start_extent,
                       position.d_y,
                       position.d_x + sel_end_extent,
                       position.d_y + vertical_space);

        d_selectionImage->render(buffer, sel_rect, clip_rect, ColourRect(0xFF002FFF));
    }

    // draw the text string.
    fnt->drawText(buffer, d_text, final_pos, clip_rect, final_cols,
                  space_extra, 1.0f, y_scale);
}