/***************************************************************************
 *   Copyright (C) 2005 by Daniel Stöckel                                  *
 *   the_docter@gmx.net                                                    *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "kommando.h"

#include <tdelocale.h>
#include <X11/Xlib.h>
#include <X11/Xmu/WinUtil.h>
#include <kpixmapeffect.h>

#include "configuration.h"

Kommando::Kommando()
    :   TQWidget( 0, "Kommando", TQt::WDestructiveClose |
                    TQt::WStyle_Customize  |
                    TQt::WStyle_NoBorder),
        actMenu(0),
        navbutton(this),
        oldNavbuttonIconType(0)
{
    mTopLevelMenus.setAutoDelete(true);

    //set up the widget's properties
    resize();
    setBackgroundMode( NoBackground );

    //set up the navbutton
    Config& config = Config::getSingleton();
    navbutton.move(config.menuRadius(),config.menuRadius());
    connect(&navbutton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotNavClick()));
}

void Kommando::slotGlobAccel()
{
    toggle();
}

void Kommando::show( )
{
    Window   rep_root, rep_child;
    int      rep_rootx, rep_rooty;
    unsigned int  rep_mask;
    int      mousex, mousey;
    Display* dpy = tqt_xdisplay();
    Window   win = tqt_xrootwin();
    XClassHint hint;

    hint.res_class = 0;
    hint.res_name = 0;

    //Get mouse coursor position and the application name of the window under the coursor
    XQueryPointer (dpy, win, &rep_root, &rep_child, &rep_rootx, &rep_rooty, &mousex, &mousey, &rep_mask);

    rep_child = XmuClientWindow(dpy,rep_child);
    if(XGetClassHint(dpy,rep_child,&hint) != 0){
        setActTopLevelMenu(hint.res_class);
    } else {
        setActTopLevelMenu("default");
    }
    if(hint.res_class){
        XFree(hint.res_class);
    }
    if(hint.res_name){
        XFree(hint.res_name);
    }

    Config& config = Config::getSingleton();
    move(mousex-config.menuRadius(),mousey-config.menuRadius());

    //get the part of the screen the widget is drawn onto and apply a fade effect to it
    mScreenshot = TQPixmap::grabWindow( tqt_xrootwin(), x(), y(), width(), height() );
    KPixmapEffect::fade( mScreenshot, config.opacity(), config.tintColor() );

    TQWidget::show();
}

void Kommando::hide( )
{
    selectButton(BUTTON_DESELECT);
    TQWidget::hide();
}

void Kommando::toggle( )
{
    if(!isHidden()){
        hide();
    } else {
        show();
    }
}

void Kommando::setActMenu( Menu * newMenu )
{
    //disconnect everything
    if(actMenu != 0){
        actMenu->disconnect();
        actMenu->hideButtons();
    }

    if(newMenu != 0){
        if(mTopLevelMenus.containsRef(newMenu)){
            navbutton.setIcon("error");
        } else {
            navbutton.setIcon("back");
        }

        //initialize the new menu
        connect(newMenu, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(slotOnClick()) );
        connect(newMenu, TQ_SIGNAL(buttonSelected(int)),this,TQ_SLOT(slotButtonSelected(int)));
        newMenu->showButtons();
    }
    actMenu = newMenu;
}

void Kommando::setActTopLevelMenu(const TQString& appName )
{
    Menu* menu = 0;
    for(Menu* it = mTopLevelMenus.first(); it != 0; it = mTopLevelMenus.next()){
        if (it->appName() == appName){
            menu = it;
            break;
        }
        //get a default menu, assume that a toplevel menu with TQString::null or "default" as appname is one
        if ((it->appName() == TQString::null) || (it->appName() == "default")){
            menu = it;
        }
    }
    setActMenu(menu);
}

void Kommando::setTopLevelMenus( const TQPtrList<Menu>& newmenus )
{
    setActMenu(0);
    //No need to clear the list, because autoDelete is turned on in
    //mTopLevelMenus
    mTopLevelMenus = newmenus;
}

void Kommando::windowActivationChange( bool oldActive )
{
    //if the menu loses focus hide it
    if(oldActive){
        hide();
    }
}

void Kommando::paintEvent( TQPaintEvent * evt )
{
    TQPainter p(this);
    p.drawPixmap(evt->rect().topLeft(),mScreenshot,evt->rect());
}

void Kommando::wheelEvent( TQWheelEvent * evt )
{
    actMenu->selectButton(actMenu->selectedButtonNum()+evt->delta()/120);
}

void Kommando::execute( )
{
    if(!isHidden()){
        Menu* temp = actMenu->execute();
        if(temp){
            setActMenu(temp);
        } else {
            hide();
        }
    }
}

void Kommando::slotOnClick( )
{
    execute();
}

void Kommando::slotNavClick( )
{
    if(actMenu->selectedButtonNum()==BUTTON_DESELECT){
        if(mTopLevelMenus.containsRef(actMenu)){
            hide();
        } else {
            setActMenu(actMenu->parentMenu());
        }
    } else {
        execute();
    }
}

void Kommando::slotButtonSelected( int type )
{
    if(oldNavbuttonIconType != type){
        switch(type){
            case 0:
                if(mTopLevelMenus.containsRef(actMenu)){
                    navbutton.setIcon("error");
                } else {
                    navbutton.setIcon("back");
                }
                break;
            case RoundButton::Commando:
                navbutton.setIcon("application-x-executable");
                break;
            case RoundButton::Submenu:
                navbutton.setIcon("folder");
                break;
        }
        oldNavbuttonIconType=type;
    }
}

void Kommando::keyPressEvent( TQKeyEvent * evt )
{
    switch(evt->key()){
        case TQt::Key_Left:
            actMenu->selectButton(actMenu->selectedButtonNum()-1);
            break;
        case TQt::Key_Right:
            actMenu->selectButton(actMenu->selectedButtonNum()+1);
            break;
        case TQt::Key_Return:
            slotNavClick();
            break;
        case TQt::Key_Escape:
            if(mTopLevelMenus.containsRef(actMenu)){
                hide();
            } else {
                setActMenu(actMenu->parentMenu());
            }
            break;
        case TQt::Key_1:
        case TQt::Key_2:
        case TQt::Key_3:
        case TQt::Key_4:
        case TQt::Key_5:
        case TQt::Key_6:
        case TQt::Key_7:
        case TQt::Key_8:
        case TQt::Key_9:
            //We want to get the number of the button, so treat the enum as number (yes I know, but it works fine :->)
            actMenu->selectButton(evt->key() - TQt::Key_1);
        break;
    }
}

void Kommando::setNavButtonSize( unsigned short size )
{
    navbutton.setRadius(size);
    Config& config = Config::getSingleton();
    navbutton.move(config.menuRadius(),config.menuRadius());
}

void Kommando::resize( )
{
    Config& config = Config::getSingleton();
    setFixedSize(config.menuSize(),config.menuSize());
    //apply a circular mask
    TQRegion mask(rect(),TQRegion::Ellipse);
    setMask(mask);
}

void Kommando::selectButton( int num )
{
    if(!isHidden())
        actMenu->selectButton(num);
}

void Kommando::mousePressEvent(TQMouseEvent* evt)
{
    middleMouseButtonState = (evt->button() == TQt::MidButton);
}

void Kommando::mouseReleaseEvent(TQMouseEvent* evt)
{
    if(middleMouseButtonState && (evt->button() == TQt::MidButton)){
        middleMouseButtonState = false;
        slotNavClick();
    }
}

#include "kommando.moc"
