/*
 * Copyright (C) 2008 Instituto Nokia de Tecnologia. All rights reserved.
 *
 * This file is part of QZion.
 *
 * QZion is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * QZion is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with QZion.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "qziontext_p.h"


QGraphicsQZionTextItem::QGraphicsQZionTextItem(QGraphicsItem *parent)
    : QAbstractGraphicsShapeItem(parent), _text(""), _color(Qt::white), _color2(Qt::black),
      _alignment(QPointF(0.5, 0.5)), _ellipsisAlignment(0.0), _style(NoStyle)
{
    updateBoundingRect();
}


QRectF QGraphicsQZionTextItem::boundingRect() const
{
    return _boundingRect;
}


/*!
    \internal
*/
void QGraphicsQZionTextItem::updateBoundingRect()
{
    int realWidth;
    int realHeight;
    int realX;
    int realY;
    QRectF fontBoundingRect;

    prepareGeometryChange();

    fontBoundingRect = QFontMetrics(_font).boundingRect(0, 0,
                                                        _size.width(),
                                                        _size.height(),
                                                        Qt::TextSingleLine |
                                                        Qt::AlignHCenter,
                                                        _text);

    // Does the bounding rect fit in the available width?
    if (fontBoundingRect.width() < _size.width()) {
        realWidth = fontBoundingRect.width();
        realX = _alignment.x() * (_size.width() - realWidth);
    } else {
        realWidth = _size.width();
        realX = 0;
    }

    // Does the bounding rect fit in the available height?
    if (fontBoundingRect.height() < _size.height()) {
        realHeight = fontBoundingRect.height();
        realY = _alignment.y() * (_size.height() - realHeight);
    } else {
        realHeight = _size.height();
        realY = 0;
    }

     switch (_style) {
        case OutLine:
            _boundingRect = QRectF(realX + 1, realY + 1, realWidth + 1, realHeight + 1);
            break;
        case Shadow:
            _boundingRect = QRectF(realX, realY, realWidth + 1, realHeight + 1);
            break;
        case NoStyle:
            // fall through
        default:
            _boundingRect = QRectF(realX, realY, realWidth, realHeight);
            break;
    }

    _boundingRect = QRectF(realX, realY, realWidth, realHeight);

    update();
}


void QGraphicsQZionTextItem::paint(QPainter *painter,
                                   const QStyleOptionGraphicsItem *option,
                                   QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->save();

    painter->setPen(_color);
    painter->setFont(_font);

    QRectF rt = boundingRect();
    QString text;
    int flags = Qt::TextSingleLine | Qt::AlignHCenter;

    if ((int) rt.width() == _size.width()) {
        if (_ellipsisAlignment >= 0.5)
            text = QFontMetricsF(_font).elidedText(_text, Qt::ElideLeft, rt.width());
        else
            text = QFontMetricsF(_font).elidedText(_text, Qt::ElideRight, rt.width());
    } else {
        text = _text;
    }

    switch (_style) {
        case NoStyle:
            painter->drawText(rt, flags, text);
            break;
        case OutLine:
            drawTextWithOutline(painter, rt, flags, text);
            break;
        case Shadow:
            drawTextWithShadow(painter, rt, flags, text);
            break;
        default:
            break;
    }

    painter->restore();
}


void QGraphicsQZionTextItem::drawTextWithOutline(QPainter *painter, const QRectF tileRect, int flags, QString text)
{
    Q_UNUSED(flags);

    int width = 1;

    QPainterPath path;
    QFont outlineFont = QFont(_font);
    outlineFont.setStyleStrategy(QFont::ForceOutline);

    QPointF basepoint = tileRect.bottomLeft();
    basepoint.setY(basepoint.y() - width - QFontMetrics(outlineFont).descent());

    path.addText(basepoint, outlineFont, text);
    painter->setRenderHint(QPainter::Antialiasing);
    painter->setPen(QPen(_color3, width, Qt::SolidLine, Qt::RoundCap,
                    Qt::RoundJoin));
    painter->setBrush(_color);
    painter->drawPath(path);
}


void QGraphicsQZionTextItem::drawTextWithShadow(QPainter *painter, const QRectF tileRect, int flags, QString text)
{
    _color3.setAlpha(128);
    painter->setPen(_color3);
    painter->drawText(tileRect.translated(1, 1), flags, text);

    painter->setPen(_color);
    painter->drawText(tileRect, flags, text);
}


QSize QGraphicsQZionTextItem::size() const
{
    return _size;
}


void QGraphicsQZionTextItem::setSize(const QSize &size)
{
    _size = size;
    updateBoundingRect();
}


QString QGraphicsQZionTextItem::text() const
{
    return _text;
}


void QGraphicsQZionTextItem::setText(const QString &text)
{
    if (_text != text) {
        _text = text;
        updateBoundingRect();
    }
}


QGraphicsQZionTextItem::TextStyle QGraphicsQZionTextItem::style() const
{
    return _style;
}


void QGraphicsQZionTextItem::setStyle(const QGraphicsQZionTextItem::TextStyle style)
{
    if (_style != style) {
        _style = style;
        update();
    }
}


QColor QGraphicsQZionTextItem::textColor() const
{
    return _color;
}


void QGraphicsQZionTextItem::setTextColor(const QColor &color)
{
    _color = color;
    update();
}


QColor QGraphicsQZionTextItem::outlineColor() const
{
    return _color2;
}


void QGraphicsQZionTextItem::setOutlineColor(const QColor &color)
{
    _color2 = color;
    update();
}


QColor QGraphicsQZionTextItem::shadowColor() const
{
    return _color3;
}


void QGraphicsQZionTextItem::setShadowColor(const QColor &color)
{
    _color3 = color;
    update();
}


QFont QGraphicsQZionTextItem::font() const
{
    return _font;
}


void QGraphicsQZionTextItem::setFont(const QFont &font)
{
    _font = font;
    updateBoundingRect();
}


QPointF QGraphicsQZionTextItem::alignment() const
{
    return _alignment;
}


void QGraphicsQZionTextItem::setAlignment(const QPointF &alignment)
{
    _alignment = alignment;
    updateBoundingRect();
}

qreal QGraphicsQZionTextItem::ellipsisAlignment() const
{
    return _ellipsisAlignment;
}

void QGraphicsQZionTextItem::setEllipsisAlignment(const qreal alignment)
{
    _ellipsisAlignment = alignment;
    update();
}

/*!
  \reimp
*/
bool QGraphicsQZionTextItem::contains(const QPointF &point) const
{
    return _boundingRect.contains(point);
}
