/*
 *
 * Copyright (C) 2002 Richard Moore <rich@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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <qaccel.h>
#include <qlcdnumber.h>
#include <qpoint.h>
#include <qslider.h>
#include <qstylesheet.h>
#include <qtooltip.h>
#include <qvbox.h>

#include <kdebug.h>
#include <klocale.h>
#include <kmainwindow.h>
#include <kmenubar.h>
#include <kstatusbar.h>
#include <ktoolbar.h>

#include "actions.h"
#include "actions.moc"

//
// LCD Number Action
//

LCDNumberAction::LCDNumberAction( const QString &text, int accel, 
                                  QObject* receiver, const char* slot, 
                                  QObject *parent, const char *name )
                :KAction( text, accel, receiver, slot, parent, name ),
                 numDig(3), val("  0")
{
}

int LCDNumberAction::plug( QWidget *widget, int index )
{
    //do not call the previous implementation here

    if ( widget->inherits( "KToolBar" ) ) {
        
        KToolBar *tb = static_cast<KToolBar *>(widget);
        int id = KAction::getToolButtonID();
        
        QLCDNumber *lcd = createWidget( tb );
        tb->insertWidget( id, lcd->width(), lcd, index );
        addContainer( tb, id );
        
        connect( tb, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
        return containerCount() - 1;
    }

    if ( widget->inherits( "QPopupMenu" ) ) {
        QPopupMenu *pop = static_cast<QPopupMenu *>(widget);
        
        // Create item
        QHBox *box = new QHBox( pop );
        box->setMargin( 4 );
        box->setSpacing( 6 );
        
        // Icon
        QLCDNumber *num = createWidget( box );
        num->setFixedSize( QSize(18,18) );
        
        // Label
        QLabel *l = new QLabel( box );
        l->setText( text() );

        // Insert item
        int id = pop->insertItem( box, -1, index );
        addContainer( box, id );
        connect( box, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
        
        return containerCount() - 1;
    }

    return -1;
}

void LCDNumberAction::unplug( QWidget *widget )
{
    if ( widget->inherits( "KToolBar" ) ) {
        KToolBar *bar = static_cast<KToolBar *>(widget);
        int idx = findContainer( bar );

        if ( idx != -1 ) {
            bar->removeItem( menuId( idx ) );
            removeContainer( idx );
        }
    }
    else if ( widget->inherits( "QPopupMenu" ) ) {
        QPopupMenu *pop = static_cast<QPopupMenu *>(widget);
        
        int idx = findContainer( pop );
        if ( idx != -1 ) {
            pop->removeItem( menuId( idx ) );
            removeContainer( idx );
        }
    }
}

QLCDNumber *LCDNumberAction::createWidget( QWidget *parent, const char *name )
{
    QLCDNumber *lcd = new QLCDNumber( parent, name );
    lcd->setFrameStyle( QFrame::Panel | QFrame::Sunken );
    lcd->setLineWidth(2);
    lcd->setMidLineWidth(1);

    lcd->setSegmentStyle( QLCDNumber::Flat );
    lcd->setBackgroundColor( Qt::black );
    lcd->setPaletteForegroundColor( Qt::green );

    lcd->setNumDigits( numDig );
    lcd->display( val );

    if ( !text().isEmpty() )
        QToolTip::add( lcd, text() );

    connect( this, SIGNAL( valueChanged(const QString &) ),
	     lcd, SLOT( display(const QString &) ) );
    return lcd;
}

void LCDNumberAction::setNumDigits( int nDigits )
{
    numDig = nDigits;
}

void LCDNumberAction::display( int num )
{
    display( QString::number(num) );
}

void LCDNumberAction::display( const QString &s )
{
    val = s;
    emit valueChanged( val );
}

//
// Slider Action
//

SliderAction::SliderAction( int min_, int max_, int step_, int val_,
                            const QString &text, QObject *parent, 
                            const char *name )
             :KAction( parent, name ), slide(0), min(min_), max(max_), 
              step(step_), val(val_), tickStep(-1)
{
    setText( text );
}

int SliderAction::plug( QWidget *widget, int index )
{
    //do not call the previous implementation here
    kdDebug() << "Plugging Slider into class '" << widget->className() << "'" << endl;

    if ( widget->inherits( "KToolBar" ) || widget->isA("KToolBar")) {
        KToolBar *bar = static_cast<KToolBar *>(widget);

        int id = KAction::getToolButtonID();

        slide = createWidget( bar );
        setOrientation( bar->orientation() );

        int sz = (slide->orientation() == Horizontal) ? slide->width() : slide->height();
        bar->insertWidget( id, sz, slide, index );
        addContainer( bar, id );

        connect( bar, SIGNAL( orientationChanged(Orientation) ), this, 
                 SLOT( setOrientation(Orientation) ) );
        connect( bar->mainWindow(), SIGNAL( dockWindowPositionChanged(QDockWindow*) ), 
                 this, SLOT( dockChange(QDockWindow*) ) );
        connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );

        return containerCount() - 1;
    }

    if ( widget->inherits( "QPopupMenu" ) ) {
        QPopupMenu *pop = static_cast<QPopupMenu *>(widget);

        // Create item
        QHBox *box = new QHBox( pop );
        box->setMargin( 4 );
        box->setSpacing( 6 );

        // Icon
        QLabel *p = new QLabel( box );
        if ( hasIconSet() ) {
            QPixmap pix = iconSet().pixmap( QIconSet::Small, true );
            p->setPixmap( pix );
        }
        p->setFixedSize( QSize(18,18) );

        // Label
        QLabel *l = new QLabel( box );
        l->setText( text() );

        // Slider
        QSlider *sl = createWidget( box );

        // Focus handling
        sl->setFocusPolicy( QWidget::TabFocus );
        l->setBuddy( sl );
        box->setFocusProxy( sl );

        // Insert item
        int id = pop->insertItem( box, -1, index );
        addContainer( box, id );
        connect( box, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );

        return containerCount() - 1;
    }

    return -1;

}

void SliderAction::unplug( QWidget *widget )
{
    if ( widget->inherits( "KToolBar" ) )
    {
        KToolBar *bar = static_cast<KToolBar *>(widget);

        int idx = findContainer( bar );

        if ( idx != -1 ) {
            bar->removeItem( menuId( idx ) );
            removeContainer( idx );
        }

        slide = 0;
        return;
    }

    if ( widget->inherits( "QPopupMenu" ) ) {
        QPopupMenu *pop = static_cast<QPopupMenu *>(widget);

        int idx = findContainer( pop );

        if ( idx != -1 ) {
            pop->removeItem( menuId( idx ) );
            removeContainer( idx );
        }

        return;
    }
}

void SliderAction::dockChange( QDockWindow *w )
{
    //kdDebug() << "SliderAction::dockChange() Setting orientation" << endl;

    setOrientation(w->orientation());
}

void SliderAction::setOrientation( Orientation o )
{
    //kdDebug() << "SliderAction::setOrientation() Setting orientation" << endl;

    if ( !slide || o == slide->orientation() )
        return;
        
    slide->setOrientation( o );
    
    switch( o ) {
    case Horizontal:
        slide->setTickmarks( QSlider::Below );
        disconnect( slide, SIGNAL(valueChanged(int)), this, SLOT(setInverseInternal(int)) );
        connect( slide, SIGNAL(valueChanged(int)), this, SLOT(setValueInternal(int)));
        slide->setValue( val );
        break;
    case Vertical:
        slide->setTickmarks( QSlider::Right );
        disconnect( slide, SIGNAL(valueChanged(int)), this, SLOT(setValueInternal(int)));
        connect( slide, SIGNAL(valueChanged(int)), this, SLOT(setInverseInternal(int)) );
        slide->setValue( max-val );
        break;
    }
}

void SliderAction::setValueInternal( int num )
{
    //kdDebug() << "SliderAction::setValueInternal: " << num << endl;
    
    if ( val == num )
        return;
        
    val = num;
    emit valueChanged(num);
}

void SliderAction::setInverseInternal( int num )
{
    setValueInternal (max - num);
} 

void SliderAction::setValue( int num )
{
    if (val == num)
        return;
        
    val = num;
       
    if (slide) {
        if (slide->orientation() == Qt::Horizontal)
            slide->setValue (val);
        else
            slide->setValue (max-val);
    }
}


void SliderAction::setTickInterval( int ticks )
{
    tickStep = ticks;
    if ( slide )
        slide->setTickInterval( ticks );
}

QSlider *SliderAction::createWidget( QWidget *parent, const char *name )
{
    QSlider *s = new QSlider( min, max, step, val, Horizontal, parent, name );
    
    connect( s, SIGNAL(valueChanged(int)), this, SLOT(setValueInternal(int)));

    if ( tickStep > 0 )
        s->setTickInterval( tickStep );
        
    s->setTickmarks( QSlider::Below );

    if ( !text().isEmpty() )
        QToolTip::add( s, text() );

    return s;
}

int SliderAction::value() const { 
    return val;
}

//
// Toggle View Action
//

ToggleViewAction::ToggleViewAction( const QString &text, const QString &icon,
                                    const KShortcut &cut, QObject *parent, 
                                    const char *name )
                 :KRadioAction( text, icon, cut, 0, 0, parent, name ), win(0)
{
    update();
}

void ToggleViewAction::setView( QWidget *w )
{
    win = w;
    update();
}

void ToggleViewAction::update()
{
    setEnabled( win );
    setChecked( (win ? win->isVisible() : false) );
}

void ToggleViewAction::slotActivated()
{
    KRadioAction::slotActivated();
    toggleView();
}

void ToggleViewAction::toggleView()
{
    kdDebug() << "ToggleViewAction::toggleView()" << endl;

    if ( !win )
        return;

    if ( win->isVisible() )
        hideView();
    else
        showView();
}

void ToggleViewAction::showView()
{
    if ( !win )
        return;

    win->show();
    update();
}

void ToggleViewAction::hideView()
{
    if ( !win )
        return;

    win->hide();
    update();
}

