/* This file is part of the KDE project
   Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "colorpicker.h"
#include "ksopts.h"

#include <tqlayout.h>
#include <tqpainter.h>
#include <tqvbox.h>
#include <tqstyle.h>
#include <tqlineedit.h>
#include <tqlabel.h>
#include <tqpushbutton.h>

#include <tdelocale.h>

ColorPicker::ColorPicker( TQWidget *parent, const char *name )
    : KDialogBase( parent, name, true /*modal*/, i18n( "Pick Color" ),
                   KDialogBase::Ok | KDialogBase::Cancel,
                   KDialogBase::Cancel ),
      m_foregroundColor( -1 ), m_backgroundColor( -1 )
{
    TQVBox *mainWidget = makeVBoxMainWidget();

    TQWidget *sampleBox = new TQWidget( mainWidget );
    TQHBoxLayout *sampleLayout = new TQHBoxLayout( sampleBox );

    TQLabel *preview = new TQLabel( i18n( "Preview:" ), sampleBox );
    sampleLayout->addWidget( preview );

    m_sample = new TQLineEdit( i18n( "Sample Text" ), sampleBox );
    m_sample->setFocusPolicy( TQWidget::NoFocus );
    m_sample->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum,
                             m_sample->sizePolicy().verData() ) );
    sampleLayout->addWidget( m_sample );
    sampleLayout->addStretch();

    TQHBox *box = new TQHBox( mainWidget );
    TQLabel *description = new TQLabel( i18n( "&Foreground:" ), box );
    ColorBar *foregroundColor = new ColorBar( ksopts->ircColors.toValueVector(), box );
    description->setBuddy( foregroundColor );

    box = new TQHBox( mainWidget );
    description = new TQLabel( i18n( "&Background:" ), box );
    ColorBar *backgroundColor = new ColorBar( ksopts->ircColors.toValueVector(), box );
    description->setBuddy( backgroundColor );

    TQPushButton *ok = actionButton( KDialogBase::Ok );
    TQPushButton *cancel = actionButton( KDialogBase::Cancel );

    setTabOrder( foregroundColor, backgroundColor );
    setTabOrder( backgroundColor, ok );
    setTabOrder( ok, cancel );

    ok->setAutoDefault( false );
    cancel->setAutoDefault( false );

    connect( foregroundColor, TQ_SIGNAL( colorPicked( int ) ),
             this, TQ_SLOT( setForegroundColor( int ) ) );
    connect( backgroundColor, TQ_SIGNAL( colorPicked( int ) ),
             this, TQ_SLOT( setBackgroundColor( int ) ) );

    ok->setEnabled( false );

    updateSample();
}

TQString ColorPicker::colorString() const
{
    assert( m_foregroundColor != -1 );
    TQString res( TQString::number( m_foregroundColor ) );
    if ( m_backgroundColor != -1 )
    {
        res += ',';
        res += TQString::number( m_backgroundColor );
    }
    return res;
}

void ColorPicker::setForegroundColor( int col )
{
    TQPushButton * ok =actionButton( KDialogBase::Ok );
    assert( ok );
    ok->setEnabled( true );

    m_foregroundColor = col;
    updateSample();
}

void ColorPicker::setBackgroundColor( int col )
{
    m_backgroundColor = col;
    updateSample();
}

void ColorPicker::updateSample()
{
    TQColorGroup cg( colorGroup() );

    TQColor col = ksopts->textColor;
    if ( m_foregroundColor != -1 )
        col = ksopts->ircColors[ m_foregroundColor ];

    cg.setColor( TQColorGroup::Foreground, col );
    cg.setColor( TQColorGroup::Text, col );

    if ( m_backgroundColor != -1 )
    {
        col = ksopts->ircColors[ m_backgroundColor ];
        cg.setColor( TQColorGroup::Background, col );
        cg.setColor( TQColorGroup::Base, col );
    }

    m_sample->setPalette( TQPalette( cg, cg, cg ) );
}

ColorBar::ColorBar( const TQValueVector<TQColor> &colors, TQWidget *parent, 
                      const char *name )
    : TQFrame( parent, name, WStaticContents | WRepaintNoErase ),
      m_currentCell( -1 ), m_focusedCell( - 1 ), m_colors( colors ), 
      m_cellSize( 0 )
{
    setFrameStyle( StyledPanel | Sunken );

    updateCellSize();

    setFocusPolicy( TQWidget::StrongFocus );
}

void ColorBar::drawContents( TQPainter *p )
{
    int x = contentsRect().x();
    int y = contentsRect().y();
    for ( unsigned int i = 0; i < m_colors.size(); ++i, x += m_cellSize )
    {
        bool isCurrentCell = ( m_currentCell != -1 && 
                               i == static_cast<uint>( m_currentCell ) );
        bool isFocusedCell = ( m_focusedCell != -1 && 
                               i == static_cast<uint>( m_focusedCell ) );
        drawCell( p, x, y, m_colors[ i ], TQString::number( i ), 
                  isFocusedCell, isCurrentCell );
    }
}

void ColorBar::keyPressEvent( TQKeyEvent *ev )
{
    if ( m_focusedCell == -1 ) {
        TQFrame::keyPressEvent( ev );
        return;
    }

    switch ( ev->key() )
    {
        case Key_Left:
            if ( m_focusedCell > 1 )
                m_focusedCell--;
            update();
            ev->accept();
            return;
        case Key_Right:
            if ( static_cast<uint>( m_focusedCell ) < m_colors.size() - 1 )
                m_focusedCell++;
            update();
            ev->accept();
            return;
        case Key_Enter:
        case Key_Return:
        case Key_Space:
            setCurrentCell( m_focusedCell );
            update();
            ev->accept();
            return;
        default: break;
    }

    TQFrame::keyPressEvent( ev );
}

void ColorBar::focusInEvent( TQFocusEvent *ev )
{
    if ( ev->reason() == TQFocusEvent::Tab ||
         ev->reason() == TQFocusEvent::Backtab )
        m_focusedCell = 0;
    TQFrame::focusInEvent( ev );
}

void ColorBar::focusOutEvent( TQFocusEvent *ev )
{
    if ( ev->reason() == TQFocusEvent::Tab ||
         ev->reason() == TQFocusEvent::Backtab ||
         ev->reason() == TQFocusEvent::Mouse )
        m_focusedCell = -1;
    TQFrame::focusOutEvent( ev );
}

void ColorBar::fontChange( const TQFont &oldFont )
{
    updateCellSize();
    TQFrame::fontChange( oldFont );
}

void ColorBar::styleChange( TQStyle &oldStyle )
{
    updateCellSize();
    TQFrame::styleChange( oldStyle );
}

bool ColorBar::focusNextPrevChild( bool next )
{
    if ( next )
    {
        assert( m_focusedCell != -1 );

        if ( static_cast<uint>( m_focusedCell ) < m_colors.size() - 1 )
        {
            m_focusedCell++;
            update();
            return true;
        }
        return TQFrame::focusNextPrevChild( next );
    }

    if ( m_focusedCell > 1 )
    {
        m_focusedCell--;
        update();
        return true;
    }

    return TQFrame::focusNextPrevChild( next );
}

void ColorBar::mousePressEvent( TQMouseEvent *ev )
{
    const TQPoint &p = ev->pos();
    if ( contentsRect().contains( p ) )
    {
        m_focusedCell = p.x() / m_cellSize;
        update();
    }

    TQFrame::mousePressEvent( ev );
}

void ColorBar::mouseReleaseEvent( TQMouseEvent *ev )
{
    if ( m_focusedCell != -1 )
    {
        setCurrentCell( m_focusedCell );
        update();
    }
    TQFrame::mouseReleaseEvent( ev );
}

void ColorBar::updateCellSize()
{
    setLineWidth( style().pixelMetric( TQStyle::PM_DefaultFrameWidth, this ) );

    TQFontMetrics metrics( font() );

    m_cellSize = metrics.width( TQString::number( m_colors.size() ) ) +
                 ( s_indicatorSize * 2 ) +
                 ( s_focusSize * 2 ) +
                 ( s_innerMargin * 2 );

    setFixedSize( TQSize( ( m_colors.size() * m_cellSize ) + ( frameWidth() * 2 ), 
                         m_cellSize + ( frameWidth() * 2 ) ) );
}

void ColorBar::setCurrentCell( int cell )
{
    m_currentCell = cell;
    emit colorPicked( cell );
}

void ColorBar::drawCell( TQPainter *p, int x, int y, const TQColor &color,
                         const TQString &text, bool isFocusedCell, 
                         bool isCurrentCell )
{
    p->fillRect( x, y, m_cellSize, m_cellSize, color );

    TQColor penColor = black;
    // ### hack
    if ( color.red() < 127 && color.green() < 127 && color.blue() < 127 )
        penColor = white;
        
    p->setPen( penColor );

    if ( isCurrentCell )
    {
        p->fillRect( x, y, m_cellSize, s_indicatorSize, penColor );
        p->fillRect( x, y + s_indicatorSize, 
                     s_indicatorSize, m_cellSize - ( 2 * s_indicatorSize ), penColor );
        p->fillRect( x, y + m_cellSize - s_indicatorSize, 
                     m_cellSize, s_indicatorSize, penColor );
        p->fillRect( x + m_cellSize - s_indicatorSize, y + s_indicatorSize,
                     s_indicatorSize, m_cellSize - ( 2 * s_indicatorSize ), penColor );
    }

    if ( isFocusedCell )
    {
        int focusRectSize = m_cellSize - ( 2 * s_indicatorSize );

        p->fillRect( x + s_indicatorSize, y + s_indicatorSize, 
                     focusRectSize, s_focusSize, penColor );
        p->fillRect( x + s_indicatorSize, y + s_indicatorSize + s_focusSize, 
                     s_focusSize, focusRectSize - ( 2 * s_focusSize ), penColor );
        p->fillRect( x + s_indicatorSize, 
                     y + m_cellSize - s_indicatorSize - s_focusSize,
                     focusRectSize, s_focusSize, penColor );
        p->fillRect( x + m_cellSize - s_indicatorSize - s_focusSize, 
                     y + s_indicatorSize + s_focusSize, 
                     s_focusSize, focusRectSize - ( 2 * s_focusSize ), penColor );
    }

    TQFontMetrics metrics( p->font() );

    int offset = ( m_cellSize / 2 ) - ( metrics.width( text ) / 2 );
    p->drawText( x + offset, y + s_focusSize + s_indicatorSize + 
                 + metrics.ascent(), text );
}
 
#include "colorpicker.moc"
