/***************************************************************************
 *   Copyright (C) 2004 by Hans Oischinger                                 *
 *   hans.oischinger@kde-mail.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 "komposetaskwidget.h"

#include "komposetaskmanager.h"
#include "komposeviewmanager.h"
#include "komposetask.h"
#include "komposetaskcontainerwidget.h"
#include "komposetaskprefswidget.h"
#include "komposesettings.h"
#include "komposeglobal.h"
#include "komposesettings.h"

#include <tqpixmap.h>
#include <tqimage.h>
#include <tqpainter.h>
#include <tqdragobject.h>
#include <tqapplication.h>
#include <tqtooltip.h>
#include <tqiconset.h>
#include <tqtimer.h>
#include <tqcolor.h>
#include <tqfont.h>

#include <kcursor.h>
#include <tdelocale.h>
#include <tdepopupmenu.h>
#include <tdeactioncollection.h>
#include <tdeaction.h>
#include <tdeapplication.h>
#include <kiconloader.h>
#include <kdebug.h>

#include "komposetaskvisualizer.h"

KomposeTaskWidget::KomposeTaskWidget(KomposeTask *t, TQWidget *parent, KomposeLayout *l, const char *name)
    : KomposeWidget(parent, l, name),
    highlight(false),
    task(t)
{
  setWFlags( WStaticContents | WRepaintNoErase | WResizeNoErase );  // avoid redraw errors
  setBackgroundMode( TQt::NoBackground );  // avoid flickering

  TQToolTip::add( this, task->visibleNameWithState() );

  pm_dbBackground.setOptimization( TQPixmap::BestOptim );
  setBackgroundMode( TQt::NoBackground );
  //setBackgroundPixmap(pm_dbBackground);

  initActions();
  initMenu();
  prefWidget = new KomposeTaskPrefsWidget( this, "Task prefs" );
  prefWidget->hide();
  setActionIcons();

  //connect( t, TQ_SIGNAL( destroyed() ), this, TQ_SLOT( slotTaskDestroyed() ) );
  connect( t, TQ_SIGNAL( closed() ), this, TQ_SLOT( slotTaskDestroyed() ) );
  connect( t, TQ_SIGNAL( stateChanged() ), this, TQ_SLOT( drawWidgetAndRepaint() ) );
  connect( t, TQ_SIGNAL( stateChanged() ), this, TQ_SLOT( reInitMenu() ) );

#ifdef COMPOSITE
  if ( KomposeGlobal::instance()->hasXcomposite() && KomposeSettings::instance()->getUseComposite() )
  {
    connect( t, TQ_SIGNAL( x11DamageNotify() ), this, TQ_SLOT( drawWidgetAndRepaint() ) );
  }
#endif
  //setFocusPolicy(TQWidget::ClickFocus);
  setFocusPolicy(TQWidget::StrongFocus);

  initFonts();
}


KomposeTaskWidget::~KomposeTaskWidget()
{
  prefWidget->deleteLater();
  menu->deleteLater();
  
  delete actMinimizeRestoreTask;
  delete actCloseTask;
  delete taskActionCollection;
}

void KomposeTaskWidget::reInitMenu()
{
  delete menu;
  initMenu();
}

void KomposeTaskWidget::initFonts()
{
  titleFont = KomposeSettings::instance()->getWindowTitleFont();
}

void KomposeTaskWidget::slotTaskDestroyed()
{
  disconnect( task, TQ_SIGNAL( closed() ), this, TQ_SLOT( slotTaskDestroyed() ) );
  disconnect( task, TQ_SIGNAL( stateChanged() ), this, TQ_SLOT( drawWidgetAndRepaint() ) );
  
  //if (KomposeViewManager::instance()->hasActiveView())
  emit requestRemoval(this);
}
void KomposeTaskWidget::resizeEvent ( TQResizeEvent * e )
{
  if ( e->oldSize() != e->size())
  {
    prefWidget->move(width() - prefWidget->width() - 3, 3);
    drawWidgetAndRepaint();
  }
  KomposeWidget::resizeEvent( e );
}


void KomposeTaskWidget::paintEvent ( TQPaintEvent * )
{
  if (size().height() < 40 )  // small hack that will prevent drawing on init
    return;
    
  if ( pm_dbBackground.isNull() )
    drawWidget();
  bitBlt( this, 0, 0, &pm_dbBackground, 0, 0, width(), height() );
}

void KomposeTaskWidget::drawWidgetAndRepaint()
{
  if (size().height() < 40 )  // small hack that will prevent drawing on init
    return;
  
  drawWidget();
  repaint();
}

void KomposeTaskWidget::drawWidget()
{
  if ( !KomposeViewManager::instance()->hasActiveView() || !isShown() )
    return;
  
  pm_dbBackground.resize( width(), height() );
  //pm_dbBackground.fill(white);

  TQPainter p( &pm_dbBackground );

  int effect = IEFFECT_NONE;

  if ( KomposeSettings::instance()->getShowWindowTitles() && !task->isIconified() )
    effect = IEFFECT_TITLE;
  if ( KomposeSettings::instance()->getShowWindowTitles() && task->isIconified() )
    effect = IEFFECT_MINIMIZED_AND_TITLE;
  if ( !KomposeSettings::instance()->getShowWindowTitles() && task->isIconified() )
    effect = IEFFECT_MINIMIZED;
  //   if ( highlight )               // I hate it, so I disable it!
  //     effect = IEFFECT_HIGHLIGHT;

  task->getVisualizer()->renderOnPixmap(&pm_dbBackground, effect);

  // Icon
  TQPoint titleTextPos( 6, KomposeSettings::instance()->getWindowTitleFontHeight() + 1);
  if ( KomposeSettings::instance()->getShowIcons() )
  {
    TQPixmap icon = task->getIcon( KomposeSettings::instance()->getIconSizePixels() );

    // Place the icon left or under the text, according to it's size
    if ( KomposeSettings::instance()->getIconSize() < 2 || icon.height() < 50 )
    {
      // Medium sized or tiny Icon
      p.drawPixmap( TQPoint(5, 5), icon );
      titleTextPos.setX(icon.width() + 10);
    }
    else
    {
      // Big Icon
      p.drawPixmap( TQPoint(5, 5), icon );
      //       titleTextPos.setX(icon.width());
    }
  }

  // Title
  if ( KomposeSettings::instance()->getShowWindowTitles() )
  {
    p.setFont(titleFont);
    if ( KomposeSettings::instance()->getShowWindowTitleShadow() )
    {
      p.setPen( KomposeSettings::instance()->getWindowTitleFontShadowColor() );
      p.drawText( titleTextPos, task->visibleNameWithState() );
    }
    p.setPen( KomposeSettings::instance()->getWindowTitleFontColor() );
    p.drawText( TQPoint( titleTextPos.x()-2, titleTextPos.y()-2 ), task->visibleNameWithState() );
  }

  // Border
  TQColor borderColor;
  int borderWidth, borderStyle;

  if (highlight)
  {
    borderColor = KomposeSettings::instance()->getWindowBorderActiveColor();
    borderWidth = KomposeSettings::instance()->getWindowBorderActiveWidth();
    borderStyle = KomposeSettings::instance()->getWindowBorderActiveStyle();
  }
  else
  {
    borderColor = KomposeSettings::instance()->getWindowBorderInactiveColor();
    borderWidth = KomposeSettings::instance()->getWindowBorderInactiveWidth();
    borderStyle = KomposeSettings::instance()->getWindowBorderInactiveStyle();
  }

  TQPen pen(borderColor, borderWidth, static_cast<TQt::PenStyle>(borderStyle));

  p.setPen(pen);
  p.drawRect(rect());
  p.end();
}

void KomposeTaskWidget::mouseReleaseEvent ( TQMouseEvent * e )
{
  if ( !rect().contains( e->pos() ) )
    return;
  KomposeViewManager::instance()->activateTask( task );
}

void KomposeTaskWidget::mouseMoveEvent ( TQMouseEvent * e )
{
  if ( e->state() == TQt::LeftButton )
    startDrag();
}

// void KomposeTaskWidget::mouseDoubleClickEvent ( TQMouseEvent * e )
// {
//   if ( !rect().contains( e->pos() ) )
//     return;
//   KomposeTaskManager::instance()->activateTask( task );
// }

void KomposeTaskWidget::keyReleaseEvent ( TQKeyEvent * e )
{
  if ( e->key() == TQt::Key_Return || e->key() == TQt::Key_Space )
  {
    kdDebug() << "KomposeTaskWidget::keyReleaseEvent - activating Task!" << endl;
    e->accept();
    KomposeViewManager::instance()->activateTask( task );
    return;
  }
  else if ( e->key() == TQt::Key_C )
  {
    kdDebug() << "KomposeTaskWidget::keyReleaseEvent - closing Task!" << endl;
    task->close();
    e->accept();
  }
  else if ( e->key() == TQt::Key_M )
  {
    kdDebug() << "KomposeTaskWidget::keyReleaseEvent - toggling state!" << endl;
    task->minimizeOrRestore();
    e->accept();
  }
  else
  {
    kdDebug() << "KomposeTaskWidget::keyReleaseEvent - ignored..." << endl;
    e->ignore();
  }
  KomposeWidget::keyReleaseEvent(e);
}

void KomposeTaskWidget::leaveEvent ( TQEvent * )
{
  highlight = false;
  unsetCursor();
//   drawWidgetAndRepaint();

  prefWidget->hide();
  if ( parentWidget() )
    parentWidget()->setFocus();
}

void KomposeTaskWidget::enterEvent ( TQEvent * )
{
  setFocus();
  setCursor( KCursor::handCursor() );
  highlight = true;
//   drawWidgetAndRepaint();

  prefWidget->show();
}

void KomposeTaskWidget::focusInEvent ( TQFocusEvent * )
{
  highlight = true;
  drawWidgetAndRepaint();
}

void KomposeTaskWidget::focusOutEvent ( TQFocusEvent * )
{
  highlight = false;
  drawWidgetAndRepaint();
}

int KomposeTaskWidget::getHeightForWidth ( int w ) const
{
  //kdDebug() << "KomposeTaskWidget::getHeightForWidth()");
  return task->getHeightForWidth(w);
}

int KomposeTaskWidget::getWidthForHeight ( int h ) const
{
  //kdDebug() << "KomposeTaskWidget::getWidthForHeight()");
  return task->getWidthForHeight(h);
}

double KomposeTaskWidget::getAspectRatio()
{
  //kdDebug() << "KomposeTaskWidget::getAspectRatio()");
  return task->getAspectRatio();
}

void KomposeTaskWidget::startDrag()
{
  // The text is just a dummy
  // FIXME: Maybe we should us a "Task"-Mimetype
  TQDragObject *d = new TQTextDrag( "toDesktop()", this );
  d->dragCopy();
}

void KomposeTaskWidget::setGeometry( const TQRect &rect )
{
  int width = task->getGeometry().width();
  int height = task->getGeometry().height();

  // Don't scale images bigger than they actually are
  if ( rect.width() > width || rect.height() > height )
  {
    TQWidget::setGeometry( TQRect( rect.left(), rect.top(), width, height ) );
  }
  else
    TQWidget::setGeometry( rect );
}

void KomposeTaskWidget::initActions()
{
  taskActionCollection = new TDEActionCollection( this );

  actCloseTask = new TDEAction( i18n("Close"), "window-close", Key_Delete , task,
                              TQ_SLOT( close() ), taskActionCollection, "closeTask" );
  actCloseTask->setToolTip(i18n("Close"));
  actMinimizeRestoreTask = new TDEAction( i18n("Minimize/Restore"), "", TDEShortcut() , this,
                                        TQ_SLOT( slotMinimizeRestoreToggled() ), taskActionCollection, "minimizeRestoreTask" );
}

void KomposeTaskWidget::initMenu()
{
  menu = new TDEPopupMenu();

  actMinimizeRestoreTask->plug(menu);

  // toDesktop menu
  TQPopupMenu* m = new TQPopupMenu( this );
  m->setCheckable( true );

  int id = m->insertItem( i18n("&All Desktops"), task, TQ_SLOT( toDesktop(int) ) );
  m->setItemParameter( id, 0 ); // 0 means all desktops
  m->setItemChecked( id, task->isOnAllDesktops() );

  m->insertSeparator();

  for( int i = 1; i <= KomposeTaskManager::instance()->getNumDesktops(); i++ )
  {
    TQString name = TQString( "&%1 %2" ).arg( i ).arg( KomposeTaskManager::instance()->getDesktopName( i ).replace( '&', "&&" ) );
    id = m->insertItem( name, task, TQ_SLOT( toDesktop(int) ) );
    m->setItemParameter( id, i );
    m->setItemChecked( id, !task->isOnAllDesktops() && task->onDesktop() == i );
  }
  menu->insertItem(i18n("To &Desktop"), m);
  
  menu->insertSeparator();
  actCloseTask->plug(menu);

}

/**
 * Set the toggle icons for some actions
 *
 * The inverse flag is a hack to allow toggling of the icons when the minimized/restored event
 * hasn't yet reached the Task object ( which is the case on buttonpress)
 */
void KomposeTaskWidget::setActionIcons( bool inverse )
{
kdDebug() << "setIconSet" << endl;
  if ( ( task->isIconified() && !inverse ) || ( !task->isIconified() && inverse ) )
    actMinimizeRestoreTask->setIconSet( kapp->iconLoader()->loadIconSet ( "go-up", TDEIcon::NoGroup, 16 ) );
  else
    actMinimizeRestoreTask->setIconSet( kapp->iconLoader()->loadIconSet ( "go-bottom", TDEIcon::NoGroup, 16 ) );
}

void KomposeTaskWidget::slotMinimizeRestoreToggled()
{
  setActionIcons( true );
  task->minimizeOrRestore();
}

void KomposeTaskWidget::mousePressEvent ( TQMouseEvent * e )
{
  if ( !rect().contains( e->pos() ) )
    return;

  switch ( e->button() )
  {
  case LeftButton:
    break;
  case MidButton:
    // fall through
  case RightButton:
    menu->popup( e->globalPos() );
    break;
  default:
    // nothing
    break;
  }
}

#include "komposetaskwidget.moc"
