/* kasgroupitem.cpp
**
** Copyright (C) 2001-2003 Richard Moore <rich@kde.org>
** Contributor: Mosfet
**     All rights reserved.
**
** KasBar is dual-licensed: you can choose the GPL or the BSD license.
** Short forms of both licenses are included below.
*/

/*
** 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 in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
** MA 02111-1307, USA.
*/

/*
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
**    notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
**    notice, this list of conditions and the following disclaimer in the
**    documentation and/or other materials provided with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
*/

/*
** Bug reports and questions can be sent to kde-devel@kde.org
*/
#include <qpainter.h>
#include <qbitmap.h>
#include <qtimer.h>
#include <qwmatrix.h>

#include <kglobal.h>
#include <kwin.h>
#include <kiconloader.h>
#include <kpixmap.h>
#include <kpixmapeffect.h>
#include <kpopupmenu.h>
#include <klocale.h>

#include <taskmanager.h>
#include <taskrmbmenu.h>

#include "kastasker.h"
#include "kasgrouppopup.h"
#include "kasgroupitem.h"

#ifndef KDE_USE_FINAL
/* XPM */
static const char *tiny_floppy[]={
"10 10 4 1",
". c None",
"# c #000000",
"b c #a0a0a0",
"a c #ffffff",
".########.",
".#aaaaaa#.",
".#aaaaaa#.",
".#aaaaaa#.",
".########.",
".########.",
".##bbbb##.",
".##bbbb##.",
".##bbbb##.",
".........."};
#endif

KasGroupItem::KasGroupItem( KasTasker *parent )
   : KasItem( parent ), items()
     
{
    setCustomPopup( true );
    setGroupItem( true );
    setText( i18n("Group") );
    items.setAutoDelete( false );

    connect( parent, SIGNAL( layoutChanged() ), this, SLOT( hidePopup() ) );
    connect( parent, SIGNAL( layoutChanged() ), this, SLOT( update() ) );
}

KasGroupItem::~KasGroupItem()
{
}

KasTasker *KasGroupItem::kasbar() const
{
    return static_cast<KasTasker *> (KasItem::kasbar());
}

QPixmap KasGroupItem::icon()
{
    bool usedIconLoader = false;
    Task *t = items.first();
    if (!t)
	return KGlobal::iconLoader()->loadIcon( "kicker",
						KIcon::NoGroup,
						KIcon::SizeSmall );

    switch( kasbar()->itemSize() ) {
	case KasBar::Small:
	    return t->bestIcon( KIcon::SizeSmall, usedIconLoader );
	    break;
	case KasBar::Medium:
	    return t->bestIcon( KIcon::SizeMedium, usedIconLoader );
	    break;
	case KasBar::Large:
	    return t->bestIcon( KIcon::SizeLarge, usedIconLoader );
	    break;
    }

    return KGlobal::iconLoader()->loadIcon( "error",
					    KIcon::NoGroup,
					    KIcon::SizeSmall );
}

void KasGroupItem::paint( QPainter *p )
{
    paintFrame( p );
    paintLabel( p );
    paintBackground( p );

    //
    // Paint the icon
    //
    p->drawPixmap(10, 16, icon() );

    //
    // Item summary info
    //
    int modCount = 0;
    for ( Task *t = items.first(); t != 0 ; t = items.next() ) {
	if ( t->isModified() )
	    modCount++;
    }

    p->setPen( isShowingPopup() ? kasbar()->activePenColor() : kasbar()->inactivePenColor() );

    if ( modCount ) {
	QString modCountStr;
	modCountStr.setNum( modCount );
	p->drawText( extent()-fontMetrics().width( modCountStr )-3,
		     15+fontMetrics().ascent(),
		     modCountStr );

	QPixmap floppy( tiny_floppy );
	p->drawPixmap(extent()-12, 29, floppy );
    }

    int microsPerCol;
    switch( kasbar()->itemSize() ) {
	default:
	case KasBar::Small:
	    microsPerCol = 2;
	    break;
	case KasBar::Medium:
	    microsPerCol = 4;
	    break;
	case KasBar::Large:
	    microsPerCol = 7;
	    break;
    }

    int xpos = 3;
    int ypos = 16;

    for ( int i = 0; ( i < (int) items.count() ) && ( i < microsPerCol ); i++ ) {
	Task *t = items.at( i );
	if (!t)
	    break;

	if( t->isIconified() )
	    p->drawPixmap( xpos, ypos,
			   *(kasbar()->microMinIcon()) );
	else if ( t->isShaded() )
	    p->drawPixmap( xpos, ypos,
			   *(kasbar()->microShadeIcon()) );
	else
	    p->drawPixmap( xpos, ypos,
			   *(kasbar()->microMaxIcon()) );

	ypos += 7;
    }

    if ( ((int) items.count() > microsPerCol) && ( kasbar()->itemSize() != KasBar::Small ) ) {
	QString countStr;
	countStr.setNum( items.count() );
	p->drawText( extent()-fontMetrics().width( countStr )-3,
		     extent()+fontMetrics().ascent()-16,
		     countStr );
    }
}

void KasGroupItem::mousePressEvent( QMouseEvent *ev )
{
    if ( ev->button() == LeftButton ) {
	togglePopup();
	update();
    }
    else if ( ev->button() == RightButton ) {
	showGroupMenuAt( ev->globalPos() );
    }
}

void KasGroupItem::showGroupMenuAt( const QPoint &p )
{
    KPopupMenu *km = new KPopupMenu;
    km->insertItem( i18n("&About Kasbar"), kasbar(), SLOT( showAbout() ) );
    km->insertItem( i18n("&Configure..."), kasbar(), SLOT( showPreferences() ) );

    TaskRMBMenu *tm = new TaskRMBMenu( &items, kasbar()->taskManager(), true, kasbar() );
    tm->insertSeparator();
    tm->insertItem( i18n("&Kasbar"), km );

    mouseLeave();
    kasbar()->updateMouseOver();

    tm->exec( p );
    delete tm;
}

KasPopup *KasGroupItem::createPopup()
{
    if ( items.count() ) {
	KasGroupPopup *pop = new KasGroupPopup( this );
	KasTasker *bar = pop->childBar();

	for ( Task *t = items.first(); t != 0; t = items.next() ) {
	    bar->addTask( t );
	}
	pop->resize( bar->size() );

	return pop;
    }
    return 0;

//     // Test code
//     //
//     // This generates cool looking fractal-like patterns if you keep unfolding the
//     // groups!
//     int pos = (int) this; 
//     if ( pos % 2 )
//        bar->append( new KasItem( bar ) );
//     if ( pos % 5 )
//        bar->append( new KasItem( bar ) );
//     bar->append( new KasGroupItem( bar ) );
//     if ( pos % 3 )
//        bar->append( new KasItem( bar ) );
//     if ( pos % 7 )
//        bar->append( new KasItem( bar ) );
//     ////////////
}

void KasGroupItem::addTask( Task *t )
{
    if (!t)
	return;

    items.append( t );
    if ( items.count() == 1 )
	setText( t->visibleName() );

    connect( t, SIGNAL( changed() ), this, SLOT( update() ) );
    update();
}

void KasGroupItem::removeTask( Task *t )
{
    if ( !t )
	return;

    hidePopup();
    items.remove( t );

    if ( items.count() == 1 )
	kasbar()->moveToMain( this, items.first() );
}

#include "kasgroupitem.moc"
