/***************************************************************************
 *   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     *
 *   aint with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/
#ifndef TRANSFORMLIST_H
#define TRANSFORMLIST_H

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

class LengthAttribute;
class Angle;
class Matrix;
class TransformList;
/**
@author Hans Oischinger
*/
class Transform : public Attribute
{
public:
  Transform();
  ~Transform();
  Transform( const Transform & );

  // The following enum allows us to preserve access
  // the "easy" translation type while still being able
  // to use matrixes
  enum TansformMetaType
  {
    TRANSFORM_NULL,
    TRANSFORM_TRANSLATE,
    TRANSFORM_SCALE,
    TRANSFORM_ROTATE,
    TRANSFORM_SKEWX,
    TRANSFORM_SKEWY,
    TRANSFORM_MATRIX
  };

  Transform &operator=(const Transform &);
  virtual Attribute* clone();

  virtual void accept( AVisitor& );

  void setMatrix(const Matrix&);
  void setTranslate(double, double);
  void setTranslate(LengthAttribute&, LengthAttribute&);
  void setScale(double, double);
  void setScale(LengthAttribute&, LengthAttribute&);
  void setRotate(double, double, double);
  void setRotate(Angle&, LengthAttribute&, LengthAttribute&);
  void setSkewX(double);
  void setSkewX(Angle&);
  void setSkewY(double);
  void setSkewY(Angle&);

  void multiply(const Matrix &secondMatrix);
  void postMultiply(const Matrix &secondMatrix);
  void postTranslate(const double &x, const double &y);
  void postScale(const double &scaleFactorX, const double &scaleFactorY);
  void postRotate(const double &angle);
  void postSkewX(const double &angle);
  void postSkewY(const double &angle);

  const unsigned int transformMetaType() const { return m_transformMetaType; }
  void setTransformMetaType( unsigned int metaType ) { m_transformMetaType = metaType; }
  const QString getReadableTransformMetaType() const;

  const double getRotateAngle() const { return m_rotateAngle; }
  const double getRotateCX() const { return m_rotateCX; }
  const double getRotateCY() const { return m_rotateCY; }

  const double getTranslateX() const;
  const double getTranslateY() const;

  const double getScaleX() const;
  const double getScaleY() const;

  const double getSkewX() const { return m_skew; }
  const double getSkewY() const { return m_skew; }

  const Matrix *matrix() const { return m_matrix; };

  /**
   * Decomposes a matrix into simple transformations
   * @param tl the TransformList that will be filled with the simple transformations
   * @return false for could not decompose
   */
  bool decompose( TransformList& tl ) const;

private:
  Matrix *m_matrix;
  unsigned int m_transformMetaType;
  // We cache the rotation values:
  // Some redundancy here, but saves us lots of acos, etc
  double m_rotateAngle, m_rotateCX, m_rotateCY;  
  double m_skew;
};


/**
@author Hans Oischinger
*/
class TransformList : public Attribute, public QPtrList<Transform>
{
public:
  TransformList();
  TransformList( const TransformList & );
  ~TransformList();

  TransformList &operator=(const TransformList &);
  virtual Attribute* clone();

  virtual void accept( AVisitor& );

  virtual bool isValid() const;

  void consolidate(Transform &trans);
};

#endif
