/******************************************************************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_legend_label.h"
#include "qwt_legend_data.h"
#include "qwt_graphic.h"
#include "qwt_painter.h"
#include "qwt.h"

#include <qpainter.h>
#include <qdrawutil.h>
#include <qstyle.h>
#include <qevent.h>
#include <qstyleoption.h>

static const int ButtonFrame = 2;
static const int Margin = 2;

static QSize buttonShift( const QwtLegendLabel* w )
{
    QStyleOption option;
    option.initFrom( w );

    const int ph = w->style()->pixelMetric(
        QStyle::PM_ButtonShiftHorizontal, &option, w );
    const int pv = w->style()->pixelMetric(
        QStyle::PM_ButtonShiftVertical, &option, w );
    return QSize( ph, pv );
}

class QwtLegendLabel::PrivateData
{
  public:
    PrivateData()
        : itemMode( QwtLegendData::ReadOnly )
        , isDown( false )
        , spacing( Margin )
    {
    }

    QwtLegendData::Mode itemMode;
    QwtLegendData legendData;
    bool isDown;

    QPixmap icon;

    int spacing;
};

/*!
   Set the attributes of the legend label

   \param legendData Attributes of the label
   \sa data()
 */
void QwtLegendLabel::setData( const QwtLegendData& legendData )
{
    m_data->legendData = legendData;

    const bool doUpdate = updatesEnabled();
    if ( doUpdate )
        setUpdatesEnabled( false );

    setText( legendData.title() );
    setIcon( legendData.icon().toPixmap() );

    if ( legendData.hasRole( QwtLegendData::ModeRole ) )
        setItemMode( legendData.mode() );

    if ( doUpdate )
        setUpdatesEnabled( true );
}

/*!
   \return Attributes of the label
   \sa setData(), QwtPlotItem::legendData()
 */
const QwtLegendData& QwtLegendLabel::data() const
{
    return m_data->legendData;
}

/*!
   \param parent Parent widget
 */
QwtLegendLabel::QwtLegendLabel( QWidget* parent )
    : QwtTextLabel( parent )
{
    m_data = new PrivateData;
    setMargin( Margin );
    setIndent( Margin );
}

//! Destructor
QwtLegendLabel::~QwtLegendLabel()
{
    delete m_data;
    m_data = NULL;
}

/*!
   Set the text to the legend item

   \param text Text label
    \sa QwtTextLabel::text()
 */
void QwtLegendLabel::setText( const QwtText& text )
{
    const int flags = Qt::AlignLeft | Qt::AlignVCenter
        | Qt::TextExpandTabs | Qt::TextWordWrap;

    QwtText txt = text;
    txt.setRenderFlags( flags );

    QwtTextLabel::setText( txt );
}

/*!
   Set the item mode
   The default is QwtLegendData::ReadOnly

   \param mode Item mode
   \sa itemMode()
 */
void QwtLegendLabel::setItemMode( QwtLegendData::Mode mode )
{
    if ( mode != m_data->itemMode )
    {
        m_data->itemMode = mode;
        m_data->isDown = false;

        setFocusPolicy( ( mode != QwtLegendData::ReadOnly )
            ? Qt::TabFocus : Qt::NoFocus );
        setMargin( ButtonFrame + Margin );

        updateGeometry();
    }
}

/*!
   \return Item mode
   \sa setItemMode()
 */
QwtLegendData::Mode QwtLegendLabel::itemMode() const
{
    return m_data->itemMode;
}

/*!
   Assign the icon

   \param icon Pixmap representing a plot item

   \sa icon(), QwtPlotItem::legendIcon()
 */
void QwtLegendLabel::setIcon( const QPixmap& icon )
{
    m_data->icon = icon;

    int indent = margin() + m_data->spacing;
    if ( icon.width() > 0 )
    {
        const qreal devicePixelRatio = QwtPainter::devicePixelRatio( &icon );
        indent += icon.width() / devicePixelRatio + m_data->spacing;
    }

    setIndent( indent );
}

/*!
   \return Pixmap representing a plot item
   \sa setIcon()
 */
QPixmap QwtLegendLabel::icon() const
{
    return m_data->icon;
}

/*!
   \brief Change the spacing between icon and text

   \param spacing Spacing
   \sa spacing(), QwtTextLabel::margin()
 */
void QwtLegendLabel::setSpacing( int spacing )
{
    spacing = qMax( spacing, 0 );
    if ( spacing != m_data->spacing )
    {
        m_data->spacing = spacing;

        int indent = margin() + m_data->spacing;
        if ( m_data->icon.width() > 0 )
            indent += m_data->icon.width() + m_data->spacing;

        setIndent( indent );
    }
}

/*!
   \return Spacing between icon and text
   \sa setSpacing(), QwtTextLabel::margin()
 */
int QwtLegendLabel::spacing() const
{
    return m_data->spacing;
}

/*!
    Check/Uncheck a the item

    \param on check/uncheck
    \sa setItemMode()
 */
void QwtLegendLabel::setChecked( bool on )
{
    if ( m_data->itemMode == QwtLegendData::Checkable )
    {
        const bool isBlocked = signalsBlocked();
        blockSignals( true );

        setDown( on );

        blockSignals( isBlocked );
    }
}

//! Return true, if the item is checked
bool QwtLegendLabel::isChecked() const
{
    return m_data->itemMode == QwtLegendData::Checkable && isDown();
}

//! Set the item being down
void QwtLegendLabel::setDown( bool down )
{
    if ( down == m_data->isDown )
        return;

    m_data->isDown = down;
    update();

    if ( m_data->itemMode == QwtLegendData::Clickable )
    {
        if ( m_data->isDown )
            Q_EMIT pressed();
        else
        {
            Q_EMIT released();
            Q_EMIT clicked();
        }
    }

    if ( m_data->itemMode == QwtLegendData::Checkable )
        Q_EMIT checked( m_data->isDown );
}

//! Return true, if the item is down
bool QwtLegendLabel::isDown() const
{
    return m_data->isDown;
}

//! Return a size hint
QSize QwtLegendLabel::sizeHint() const
{
    QSize sz = QwtTextLabel::sizeHint();
    sz.setHeight( qMax( sz.height(), m_data->icon.height() + 4 ) );

    if ( m_data->itemMode != QwtLegendData::ReadOnly )
    {
        sz += buttonShift( this );
        sz = qwtExpandedToGlobalStrut( sz );
    }

    return sz;
}

//! Paint event
void QwtLegendLabel::paintEvent( QPaintEvent* e )
{
    const QRect cr = contentsRect();

    QPainter painter( this );
    painter.setClipRegion( e->region() );

    if ( m_data->isDown )
    {
        qDrawWinButton( &painter, 0, 0, width(), height(),
            palette(), true );
    }

    painter.save();

    if ( m_data->isDown )
    {
        const QSize shiftSize = buttonShift( this );
        painter.translate( shiftSize.width(), shiftSize.height() );
    }

    painter.setClipRect( cr );

    drawContents( &painter );

    if ( !m_data->icon.isNull() )
    {
        QRect iconRect = cr;
        iconRect.setX( iconRect.x() + margin() );
        if ( m_data->itemMode != QwtLegendData::ReadOnly )
            iconRect.setX( iconRect.x() + ButtonFrame );

        const qreal devicePixelRatio = QwtPainter::devicePixelRatio( &m_data->icon );
        iconRect.setSize( m_data->icon.size() / devicePixelRatio );
        iconRect.moveCenter( QPoint( iconRect.center().x(), cr.center().y() ) );

        painter.drawPixmap( iconRect, m_data->icon );
    }

    painter.restore();
}

//! Handle mouse press events
void QwtLegendLabel::mousePressEvent( QMouseEvent* e )
{
    if ( e->button() == Qt::LeftButton )
    {
        switch ( m_data->itemMode )
        {
            case QwtLegendData::Clickable:
            {
                setDown( true );
                return;
            }
            case QwtLegendData::Checkable:
            {
                setDown( !isDown() );
                return;
            }
            default:;
        }
    }
    QwtTextLabel::mousePressEvent( e );
}

//! Handle mouse release events
void QwtLegendLabel::mouseReleaseEvent( QMouseEvent* e )
{
    if ( e->button() == Qt::LeftButton )
    {
        switch ( m_data->itemMode )
        {
            case QwtLegendData::Clickable:
            {
                setDown( false );
                return;
            }
            case QwtLegendData::Checkable:
            {
                return; // do nothing, but accept
            }
            default:;
        }
    }
    QwtTextLabel::mouseReleaseEvent( e );
}

//! Handle key press events
void QwtLegendLabel::keyPressEvent( QKeyEvent* e )
{
    if ( e->key() == Qt::Key_Space )
    {
        switch ( m_data->itemMode )
        {
            case QwtLegendData::Clickable:
            {
                if ( !e->isAutoRepeat() )
                    setDown( true );
                return;
            }
            case QwtLegendData::Checkable:
            {
                if ( !e->isAutoRepeat() )
                    setDown( !isDown() );
                return;
            }
            default:;
        }
    }

    QwtTextLabel::keyPressEvent( e );
}

//! Handle key release events
void QwtLegendLabel::keyReleaseEvent( QKeyEvent* e )
{
    if ( e->key() == Qt::Key_Space )
    {
        switch ( m_data->itemMode )
        {
            case QwtLegendData::Clickable:
            {
                if ( !e->isAutoRepeat() )
                    setDown( false );
                return;
            }
            case QwtLegendData::Checkable:
            {
                return; // do nothing, but accept
            }
            default:;
        }
    }

    QwtTextLabel::keyReleaseEvent( e );
}

#if QWT_MOC_INCLUDE
#include "moc_qwt_legend_label.cpp"
#endif
