/*************************************************************************
	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;
    }
}
/*************************************************************************
	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);
}
//----------------------------------------------------------------------------//
Size FormattedListboxTextItem::getPixelSize(void) const
{
    if (!d_owner)
        return Size(0, 0);

    // 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
    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;
    }

    return Size(d_formattedRenderedString->getHorizontalExtent(),
                d_formattedRenderedString->getVerticalExtent());
}
//----------------------------------------------------------------------------//
void FormattedListboxTextItem::updateString() const
{
	bool StringChanged = !d_renderedStringValid;
	if (StringChanged) parseTextString();

	if (!d_formattedRenderedString) setupStringFormatter();
	else if (StringChanged) d_formattedRenderedString->setRenderedString(d_renderedString);

	// 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 (StringChanged || area_sz != d_formattingAreaSize)
	{
		d_formattedRenderedString->format(area_sz);
		d_formattingAreaSize = area_sz;
	}
}
/*************************************************************************
    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;
    }
}
/*************************************************************************
    Return the rendered pixel size of this tree item.
*************************************************************************/
Size TreeItem::getPixelSize(void) const
{
    Font* fnt = getFont();

    if (!fnt)
        return Size(0, 0);

    if (!d_renderedStringValid)
        parseTextString();

    Size sz(0.0f, 0.0f);

    for (size_t i = 0; i < d_renderedString.getLineCount(); ++i)
    {
        const Size line_sz(d_renderedString.getPixelSize(i));
        sz.d_height += line_sz.d_height;

        if (line_sz.d_width > sz.d_width)
            sz.d_width = line_sz.d_width;
    }

    return sz;
}