/***************************************************************************
 *   Copyright (C) 2004 by Hans Oischinger                                 *
 *   hans.oischinger@kdemail.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.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/
#include "gradientpreview.h"

// Elements
#include "elements/elementtreeiterator.h"
#include "elements/gradient.h"
#include "elements/lineargradient.h"
#include "elements/transformlist.h"
#include "elements/animatedtransformlist.h"
#include "elements/animatedenum.h"
#include "elements/enumeration.h"
#include "elements/lengthattribute.h"
#include "elements/animatedlengthattr.h"

// Visitors
#include "visitors/vdrawelements.h"
#include "visitors/vsetanimvalues.h"
#include "visitors/deepclonevisitor.h"

// KDE
#include <kdebug.h>

// KCanvas
#include <kcanvas/KCanvas.h>
#include <kcanvas/KCanvasCreator.h>

#include <kcanvas/device/KRenderingStyle.h>
#include <kcanvas/device/KRenderingDevice.h>
#include <kcanvas/device/KRenderingPaintServer.h>
#include <kcanvas/device/KRenderingPaintServerSolid.h>
#include <kcanvas/device/KRenderingPaintServerGradient.h>
#include <kcanvas/device/KRenderingFillPainter.h>
#include <kcanvas/device/KRenderingStrokePainter.h>

#define FIXEDHEIGHT 25

GradientPreview::GradientPreview(QWidget *parent, const char *name)
    : CanvasWidget(parent, name),
    m_gradient(0),
    m_canvasItem(0),
    m_orientation(Qt::Horizontal)
{
  setFixedHeight(FIXEDHEIGHT);
  initCanvasItem();
}

GradientPreview::~GradientPreview()
{}

void GradientPreview::setGradient( Gradient &g )
{
  //   kdDebug() << k_funcinfo << endl;
  if (m_gradient)
  {
    m_gradient->deleteSubTree();
    m_gradient = 0;
  }
  DeepCloneVisitor* deepCloner = new DeepCloneVisitor();
  g.accept( *deepCloner );
  m_gradient = ::qt_cast<Gradient*>(deepCloner->getClone());  // This is only safe because we already know it's type
  updatePreview();
}

void GradientPreview::setGradientRef( Gradient *g )
{
  //   kdDebug() << k_funcinfo << endl;
  m_gradient = g;
  updatePreview();
}

void GradientPreview::updatePreview()
{
  if ( !m_canvasItem || !m_gradient )
    return;

  // rotate properly if vertical and unset any gradientTransforms
//   TransformList tl;
//   if (m_orientation == Qt::Vertical)
//   {
//     Transform *transOrientation = new Transform();
//     transOrientation->setRotate(90,0,0);
//     tl.append( transOrientation );
//   }
//   m_gradient->gradientTransformList().baseVal() = tl;

  // Unset the gradient vector for Linear Gradients
  LinearGradient* linGrad = ::qt_cast<LinearGradient*>(m_gradient);
//   if (linGrad)
//   {
//     linGrad->getX1().baseVal() = LengthAttribute(0., LengthAttribute::SVG_LENGTHTYPE_PERCENTAGE);
//     linGrad->getX2().baseVal() = LengthAttribute(100., LengthAttribute::SVG_LENGTHTYPE_PERCENTAGE);
//     linGrad->getY1().baseVal() = LengthAttribute(0., LengthAttribute::SVG_LENGTHTYPE_PERCENTAGE);
//     linGrad->getY2().baseVal() = LengthAttribute(0., LengthAttribute::SVG_LENGTHTYPE_PERCENTAGE);
//   }

  // Set dirty so that the visitors do actual work on it
  m_gradient->setDirty();

  // apply VSetAnimValues
  ElementTreeIterator itr( m_gradient );
  VSetAnimValues *vAnimTree = new VSetAnimValues();
  for( ; itr.current(); itr.next() )
    itr.current()->accept( *vAnimTree );
  delete vAnimTree;

  // apply VDrawElements
  VDrawElements *vDrawTree = new VDrawElements( m_canvas, m_canvas->renderingDevice() );
  vDrawTree->setNormalizePaintServers(true);
  m_gradient->accept(*vDrawTree);
  delete vDrawTree;

  // Set the render style
  KAbstractRenderingStyle *rectStyle = 0;
  rectStyle = m_canvasItem->style();
  if (!rectStyle)
    return;
  rectStyle->fillPainter()->setPaintServer( m_gradient->context() );

  m_canvasItem->invalidate();
}

void GradientPreview::resizeEvent( QResizeEvent *e )
{
  CanvasWidget::resizeEvent(e);
  // Set the current gradient item again to apply the fill painter
  initCanvasItem();
  updatePreview();
}

void GradientPreview::initCanvasItem( )
{
  if ( m_canvasItem )
    m_canvas->removeItem( m_canvasItem );

  KRenderingPaintServer *strokePainter = m_canvas->renderingDevice()->createPaintServer(PS_SOLID);
  KRenderingPaintServerSolid *strokePainterSolid = static_cast<KRenderingPaintServerSolid *>(strokePainter);
  strokePainterSolid->setColor(QColor("black"));

  KRenderingStyle *rectStyle = new KRenderingStyle();
  rectStyle->strokePainter()->setPaintServer(strokePainter);
  rectStyle->strokePainter()->setStrokeWidth(1);

  m_canvasItem = KCanvasCreator::self()->createPathItem(m_canvas, rectStyle,
                 KCanvasCreator::self()->createRectangle(0, 0, width(), height()) );
  m_canvas->insertItem( m_canvasItem );

}

void GradientPreview::setOrientation( Qt::Orientation orientation )
{
  m_orientation = orientation;
  updatePreview();
}



#include "gradientpreview.moc"
