/***************************************************************************
 *   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.             *
 ***************************************************************************/
#ifndef ANIMATIONELEMENT_H
#define ANIMATIONELEMENT_H

#include "elementnode.h"
#include "timekeyedattribute.h"

#include <qstring.h>
#include <qptrlist.h>

class Attribute;
class URIReference;
class TimeAttribute;
/**
Abstract base class for all Animate Elements
@author Hans Oischinger
*/
class AnimateElement : public ElementNode
{
  Q_OBJECT
public:
  enum Fill { FILL_REMOVE, FILL_FREEZE };

  AnimateElement( URIReference &targetElem, const QString & name = "", State state = undefined );
  AnimateElement( const AnimateElement & );
  ~AnimateElement();

  AnimateElement &operator=(const AnimateElement &);

  URIReference& ref() const { return *m_ref; }
  TimeAttribute& getStartTime() const { return *m_begin; }
  TimeAttribute& getSimpleDuration() const { return *m_duration; }

  void setFill( unsigned int fill ) { m_fill = fill; }
  unsigned int getFill() const { return m_fill; }

  virtual bool isAdditive() const { return m_additive; }
  virtual void setAdditive( bool b ) { m_additive = b; }

  // virtual Attribute* targetAttribute() const = 0; // I believe we don't need this

  virtual Element::Hit hits( const QPoint & ) { return Element::NOHIT; }
  virtual QRect bbox( KCBBoxFlags flags = BBOX_DEFAULT ) const;

  virtual void accept( Visitor& visitor );
  virtual Attribute* getAttrByName( const QString& name );

protected:
  URIReference* m_ref;
  unsigned int m_fill;
  TimeAttribute *m_begin;
  TimeAttribute *m_duration;
  bool m_additive;
};


class Transform;
class AnimatedTransformList;
typedef TimekeyedAttribute<Transform> TimekeyedTransform;
/**
@author Hans Oischinger
*/
class AnimateTransformElement : public AnimateElement
{
  Q_OBJECT
public:
  AnimateTransformElement( URIReference &targetElem, AnimatedTransformList *targetAttr,
                           const QString & name = "", State state = undefined );
  AnimateTransformElement( const AnimateTransformElement & );
  ~AnimateTransformElement();

  AnimateTransformElement &operator=(const AnimateTransformElement &);
  virtual ElementNode *clone();

  /**
   * Returns the target attribute of the animation
   */
  AnimatedTransformList* targetAttribute() const { return m_targetAttr; }
  virtual Attribute* getAttrByName( const QString& name );
  virtual void accept( Visitor& visitor );

  Transform& fromAttribute() const { return *m_from; }
  Transform& byAttribute() const { return *m_by; }
  Transform& toAttribute() const { return *m_to; }
  QPtrList<TimekeyedTransform>& values() const { return *m_attrList; }

protected:
  void init();

protected:
  AnimatedTransformList* m_targetAttr;
  QPtrList<TimekeyedTransform> *m_attrList;
  Transform* m_from;
  Transform* m_by;
  Transform* m_to;
};


class LengthAttribute;
class AnimatedLength;
/**
@author Hans Oischinger
*/
class AnimateLengthElement : public AnimateElement
{
  Q_OBJECT
public:
  AnimateLengthElement( URIReference &targetElem, AnimatedLength *targetAttr,
                        const QString & name = "", State state = undefined );
  AnimateLengthElement( const AnimateLengthElement & );
  ~AnimateLengthElement();

  AnimateLengthElement &operator=(const AnimateLengthElement &);
  virtual ElementNode *clone();

  /**
   * Returns the target attribute of the animation
   */
  AnimatedLength* targetAttribute() const { return m_targetAttr; }
  virtual Attribute* getAttrByName( const QString& name );
  virtual void accept( Visitor& visitor );

  LengthAttribute& fromAttribute() const { return *m_from; }
  LengthAttribute& byAttribute() const { return *m_by; }
  LengthAttribute& toAttribute() const { return *m_to; }

protected:
  AnimatedLength* m_targetAttr;
  LengthAttribute* m_from;
  LengthAttribute* m_by;
  LengthAttribute* m_to;
};


class AnimatedNumber;
class Number;
/**
@author Hans Oischinger
*/
class AnimateNumberElement : public AnimateElement
{
  Q_OBJECT
public:
  AnimateNumberElement( URIReference &targetElem, AnimatedNumber *targetAttr,
                        const QString & name = "", State state = undefined );
  ~AnimateNumberElement();
  AnimateNumberElement( const AnimateNumberElement & );

  AnimateNumberElement &operator=(const AnimateNumberElement &);
  virtual ElementNode *clone();

  /**
   * Returns the target attribute of the animation
   */
  AnimatedNumber* targetAttribute() const { return m_targetAttr; }
  virtual Attribute* getAttrByName( const QString& name );
  virtual void accept( Visitor& visitor );

  Number& fromAttribute() const { return *m_from; }
  Number& byAttribute() const { return *m_by; }
  Number& toAttribute() const { return *m_to; }

protected:
  AnimatedNumber* m_targetAttr;
  Number* m_from;
  Number* m_by;
  Number* m_to;
};


class AnimatedColor;
class ColorAttribute;
/**
@author Hans Oischinger
*/
class AnimateColorElement : public AnimateElement
{
  Q_OBJECT
public:
  AnimateColorElement( URIReference &targetElem, AnimatedColor *targetAttr,
                        const QString & name = "", State state = undefined );
  AnimateColorElement( const AnimateColorElement & );
  ~AnimateColorElement();

  AnimateColorElement &operator=(const AnimateColorElement&);
  virtual ElementNode *clone();

  /**
   * Returns the target attribute of the animation
   */
  AnimatedColor* targetAttribute() const { return m_targetAttr; }
  virtual Attribute* getAttrByName( const QString& name );
  virtual void accept( Visitor& visitor );

  ColorAttribute& fromAttribute() const { return *m_from; }
  ColorAttribute& byAttribute() const { return *m_by; }
  ColorAttribute& toAttribute() const { return *m_to; }

protected:
  AnimatedColor* m_targetAttr;
  ColorAttribute* m_from;
  ColorAttribute* m_by;
  ColorAttribute* m_to;
};

#endif
