// -*- c++ -*-
// Generated by gtkmmproc -- DO NOT MODIFY!
#ifndef _CLUTTERMM_PATH_H
#define _CLUTTERMM_PATH_H


#include <glibmm.h>

/*
 * Copyright (c) 2008  The cluttermm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <cluttermm/types.h>
#include <glibmm/object.h>
#include <cairomm/context.h>


#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct _ClutterPath ClutterPath;
typedef struct _ClutterPathClass ClutterPathClass;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Clutter
{ class Path_Class; } // namespace Clutter
namespace Clutter
{

enum PathNodeType
{
  PATH_MOVE_TO,
  PATH_LINE_TO,
  PATH_CURVE_TO,
  PATH_CLOSE,
  PATH_REL_MOVE_TO = PATH_MOVE_TO | CLUTTER_PATH_RELATIVE,
  PATH_REL_LINE_TO = PATH_LINE_TO | CLUTTER_PATH_RELATIVE,
  PATH_REL_CURVE_TO = PATH_CURVE_TO | CLUTTER_PATH_RELATIVE
};

class PathNode
{
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef PathNode CppObjectType;
  typedef ClutterPathNode BaseObjectType;

  static GType get_type() G_GNUC_CONST;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

  PathNode();

  explicit PathNode(const ClutterPathNode* gobject); // always takes a copy

  ///Provides access to the underlying C instance.
  ClutterPathNode*       gobj()       { return &gobject_; }

  ///Provides access to the underlying C instance.
  const ClutterPathNode* gobj() const { return &gobject_; }

protected:
  ClutterPathNode gobject_;

private:
  
public:
  typedef guint  size_type;
  typedef int           difference_type;

  typedef Knot          value_type;
  typedef Knot&         reference;
  typedef const Knot&   const_reference;

  // Use plain pointers for simplicity.
  typedef Knot*         iterator;
  typedef const Knot*   const_iterator;

#ifndef GLIBMM_HAVE_SUN_REVERSE_ITERATOR
  typedef std::reverse_iterator<iterator>       reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#else
  typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
                                Knot, Knot&, Knot*, ptrdiff_t> reverse_iterator;

  typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
                                Knot, const Knot&, const Knot*, ptrdiff_t> const_reverse_iterator;
#endif
  explicit PathNode(PathNodeType type);

  size_type size() const;
  bool empty() const;

  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end()   const;

  inline reverse_iterator       rbegin()       { return reverse_iterator(end()); }
  inline reverse_iterator       rend()         { return reverse_iterator(begin()); }
  inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
  inline const_reverse_iterator rend()   const { return const_reverse_iterator(begin()); }

  inline reference       front()       { return *begin();  }
  inline const_reference front() const { return *begin();  }
  inline reference       back()        { return *rbegin(); }
  inline const_reference back()  const { return *rbegin(); }

  inline reference       operator[](size_type i)       { return begin()[i]; }
  inline const_reference operator[](size_type i) const { return begin()[i]; }


};


class Path : public Glib::Object
{
  
#ifndef DOXYGEN_SHOULD_SKIP_THIS

public:
  typedef Path CppObjectType;
  typedef Path_Class CppClassType;
  typedef ClutterPath BaseObjectType;
  typedef ClutterPathClass BaseClassType;

private:  friend class Path_Class;
  static CppClassType path_class_;

private:
  // noncopyable
  Path(const Path&);
  Path& operator=(const Path&);

protected:
  explicit Path(const Glib::ConstructParams& construct_params);
  explicit Path(ClutterPath* castitem);

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

public:
  virtual ~Path();

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  static GType get_type()      G_GNUC_CONST;


  static GType get_base_type() G_GNUC_CONST;
#endif

  ///Provides access to the underlying C GObject.
  ClutterPath*       gobj()       { return reinterpret_cast<ClutterPath*>(gobject_); }

  ///Provides access to the underlying C GObject.
  const ClutterPath* gobj() const { return reinterpret_cast<ClutterPath*>(gobject_); }

  ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs.
  ClutterPath* gobj_copy();

private:

  
protected:
  Path();
  explicit Path(const Glib::ustring& description);

public:
  class Nodes;

  
  static Glib::RefPtr<Path> create();

  
  static Glib::RefPtr<Path> create(const Glib::ustring& description);


  inline Nodes nodes();
  inline const Nodes nodes() const;

  
  /** Adds a Clutter::PATH_MOVE_TO type node to the path. This is usually
   * used as the first node in a path. It can also be used in the middle
   * of the path to cause the actor to jump to the new coordinate.
   * 
   * @newin{1,0}
   * @param x The x coordinate.
   * @param y The y coordinate.
   */
  void add_move_to(int x, int y);
  
  /** Same as add_move_to() except the coordinates are
   * relative to the previous node.
   * 
   * @newin{1,0}
   * @param x The x coordinate.
   * @param y The y coordinate.
   */
  void add_rel_move_to(int x, int y);
  
  /** Adds a Clutter::PATH_LINE_TO type node to the path. This causes the
   * actor to move to the new coordinates in a straight line.
   * 
   * @newin{1,0}
   * @param x The x coordinate.
   * @param y The y coordinate.
   */
  void add_line_to(int x, int y);
  
  /** Same as add_line_to() except the coordinates are
   * relative to the previous node.
   * 
   * @newin{1,0}
   * @param x The x coordinate.
   * @param y The y coordinate.
   */
  void add_rel_line_to(int x, int y);
  
  /** Adds a Clutter::PATH_CURVE_TO type node to the path. This causes
   * the actor to follow a bezier from the last node to ( @a x_3, @a y_3) using
   * ( @a x_1, @a y_1) and ( @a x_2, @a y_2) as control points.
   * 
   * @newin{1,0}
   * @param x_1 The x coordinate of the first control point.
   * @param y_1 The y coordinate of the first control point.
   * @param x_2 The x coordinate of the second control point.
   * @param y_2 The y coordinate of the second control point.
   * @param x_3 The x coordinate of the third control point.
   * @param y_3 The y coordinate of the third control point.
   */
  void add_curve_to(int x1, int y1, int x2, int y2, int x3, int y3);
  
  /** Same as add_curve_to() except the coordinates are
   * relative to the previous node.
   * 
   * @newin{1,0}
   * @param x_1 The x coordinate of the first control point.
   * @param y_1 The y coordinate of the first control point.
   * @param x_2 The x coordinate of the second control point.
   * @param y_2 The y coordinate of the second control point.
   * @param x_3 The x coordinate of the third control point.
   * @param y_3 The y coordinate of the third control point.
   */
  void add_rel_curve_to(int x1, int y1, int x2, int y2, int x3, int y3);
  
  /** Adds a Clutter::PATH_CLOSE type node to the path. This creates a
   * straight line from the last node to the last Clutter::PATH_MOVE_TO
   * type node.
   * 
   * @newin{1,0}
   */
  void add_close();
  
  /** Adds new nodes to the end of the path as described in @a str. The
   * format is a subset of the SVG path format. Each node is represented
   * by a letter and is followed by zero, one or three pairs of
   * coordinates. The coordinates can be separated by spaces or a
   * comma. The types are:
   * 
   * <variablelist>
   * <varlistentry><term>M</term>
   * <listitem><para>
   * Adds a Clutter::PATH_MOVE_TO node. Takes one pair of coordinates.
   * </para></listitem></varlistentry>
   * <varlistentry><term>L</term>
   * <listitem><para>
   * Adds a Clutter::PATH_LINE_TO node. Takes one pair of coordinates.
   * </para></listitem></varlistentry>
   * <varlistentry><term>C</term>
   * <listitem><para>
   * Adds a Clutter::PATH_CURVE_TO node. Takes three pairs of coordinates.
   * </para></listitem></varlistentry>
   * <varlistentry><term>z</term>
   * <listitem><para>
   * Adds a Clutter::PATH_CLOSE node. No coordinates are needed.
   * </para></listitem></varlistentry>
   * </variablelist>
   * 
   * The M, L and C commands can also be specified in lower case which
   * means the coordinates are relative to the previous node.
   * 
   * For example, to move an actor in a 100 by 100 pixel square centered
   * on the point 300,300 you could use the following path:
   * 
   * <informalexample>
   * <programlisting>
   * M 250,350 l 0 -100 L 350,250 l 0 100 z
   * </programlisting>
   * </informalexample>
   * 
   * If the path description isn't valid <tt>false</tt> will be returned and no
   * nodes will be added.
   * 
   * @newin{1,0}
   * @param str A string describing the new nodes.
   * @return <tt>true</tt> is the path description was valid or <tt>false</tt>
   * otherwise.
   */
  bool add_string(const Glib::ustring& str);

   
  typedef void (* ClutterPathCallback) (const ClutterPathNode *node,
                                      gpointer               data);

  /** For instance,
   * void on_path_foreach(const Clutter::PathNode& node);
   */
  typedef sigc::slot<void, PathNode> ForEachSlot;

  //TODO: Documentation.
  void foreach(const ForEachSlot& slot);
  

  /** Returns a newly allocated string describing the path in the same
   * format as used by add_string().
   * 
   * @newin{1,0}
   * @return A string description of the path. Free with Glib::free().
   */
  Glib::ustring get_description() const;
  
  /** Replaces all of the nodes in the path with nodes described by
   *  @a str. See add_string() for details of the format.
   * 
   * If the string is invalid then <tt>false</tt> is returned and the path is
   * unaltered.
   * 
   * @newin{1,0}
   * @param str A string describing the path.
   * @return <tt>true</tt> is the path was valid, <tt>false</tt> otherwise.
   */
  void set_description(const Glib::ustring& str);

  
  /** Add the nodes of the Cairo path to the end of @a path.
   * 
   * @newin{1,0}
   * @param cpath A Cairo path.
   */
  void add_cairo_path(const Glib::RefPtr<Cairo::Path>& path);
  
  /** Add the nodes of the ClutterPath to the path in the Cairo context.
   * 
   * @newin{1,0}
   * @param cr A Cairo context.
   */
  void to_cairo_path(Glib::RefPtr<Cairo::Context>& context) const;

  
  /** Removes all nodes from the path.
   * 
   * @newin{1,0}
   */
  void clear();
  
  /** The value in @a progress represents a position along the path where
   * 0.0 is the beginning and 1.0 is the end of the path. An
   * interpolated position is then stored in @a position.
   * 
   * @newin{1,0}
   * @param progress A position along the path as a fraction of its length.
   * @param position Location to store the position.
   * @return Index of the node used to calculate the position.
   */
  guint get_position(double progress, Knot& position);
  
  /** Retrieves an approximation of the total length of the path.
   * 
   * @newin{1,0}
   * @return The length of the path.
   */
  guint get_length() const;

  #ifdef GLIBMM_PROPERTIES_ENABLED
/** SVG-style description of the path.
   *
   * You rarely need to use properties because there are get_ and set_ methods for almost all of them.
   * @return A PropertyProxy that allows you to get or set the property of the value, or receive notification when
   * the value of the property changes.
   */
  Glib::PropertyProxy<Glib::ustring> property_description() ;
#endif //#GLIBMM_PROPERTIES_ENABLED

#ifdef GLIBMM_PROPERTIES_ENABLED
/** SVG-style description of the path.
   *
   * You rarely need to use properties because there are get_ and set_ methods for almost all of them.
   * @return A PropertyProxy that allows you to get or set the property of the value, or receive notification when
   * the value of the property changes.
   */
  Glib::PropertyProxy_ReadOnly<Glib::ustring> property_description() const;
#endif //#GLIBMM_PROPERTIES_ENABLED

  #ifdef GLIBMM_PROPERTIES_ENABLED
/** An approximation of the total length of the path.
   *
   * You rarely need to use properties because there are get_ and set_ methods for almost all of them.
   * @return A PropertyProxy that allows you to get or set the property of the value, or receive notification when
   * the value of the property changes.
   */
  Glib::PropertyProxy_ReadOnly<guint> property_length() const;
#endif //#GLIBMM_PROPERTIES_ENABLED


public:

public:
  //C++ methods used to invoke GTK+ virtual functions:

protected:
  //GTK+ Virtual Functions (override these to change behaviour):

  //Default Signal Handlers::


};

class Path::Nodes
{
private:
  friend class Clutter::Path;

  ClutterPath* path_;

  inline Nodes(const Path::Nodes& other) : path_ (other.path_) {}
  explicit inline Nodes(ClutterPath* path) : path_ (path) {}
  Nodes& operator=(const Path::Nodes&);

public:
  typedef guint      size_type;
  typedef int               difference_type;
  typedef PathNode          value_type;
  typedef const value_type  const_reference;

  class const_iterator;
  class iterator;

  class reference
  {
  private:
    friend class Path::Nodes;
    friend class Path::Nodes::iterator;
    friend class Path::Nodes::const_iterator;

    ClutterPath* path_;
    guint index_;

    inline reference(ClutterPath* path, guint index)
      : path_ (path), index_ (index) {}

    // disallow the address-of operator
    reference* operator&();
    const reference* operator&() const;

  public:
    reference& operator=(const PathNode& node);
    operator PathNode() const;
  };

  class const_iterator
  {
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  protected:
    Path::Nodes::reference ref_;
#endif
  public:
    typedef std::random_access_iterator_tag iterator_category;
    typedef PathNode                        value_type;
    typedef int                             difference_type;
    typedef const value_type                reference;
    typedef void                            pointer;

    inline const_iterator() : ref_ (0, 0) {}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
    inline const_iterator(ClutterPath* path, guint index)
      : ref_ (path, index) {}

    inline bool equal(const const_iterator& b) const
      { return (ref_.index_ == b.ref_.index_); }
#endif
    reference operator*() const;
    reference operator[](difference_type i) const;

    inline const_iterator& operator++()    { ++ref_.index_; return *this; }
    inline const_iterator  operator++(int) { return const_iterator(ref_.path_, ref_.index_++); }
    inline const_iterator& operator--()    { --ref_.index_; return *this; }
    inline const_iterator  operator--(int) { return const_iterator(ref_.path_, ref_.index_--); }
  };

  class iterator : public const_iterator
  {
  public:
    typedef Path::Nodes::reference reference;

    inline iterator() {}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
    inline iterator(ClutterPath* path, guint index)
      : const_iterator(path, index) {}
#endif
    inline reference operator*() const { return ref_; }
    inline reference operator[](difference_type i) const
      { return reference(ref_.path_, ref_.index_ + i); }

    inline iterator& operator++()    { ++ref_.index_; return *this; }
    inline iterator  operator++(int) { return iterator(ref_.path_, ref_.index_++); }
    inline iterator& operator--()    { --ref_.index_; return *this; }
    inline iterator  operator--(int) { return iterator(ref_.path_, ref_.index_--); }
  };

#ifndef GLIBMM_HAVE_SUN_REVERSE_ITERATOR
  typedef std::reverse_iterator<iterator>       reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#else
  typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
                                value_type, reference, void, ptrdiff_t> reverse_iterator;
  typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
                                value_type, const_reference, void, ptrdiff_t> const_reverse_iterator;
#endif
  size_type   size() const;
  inline bool empty() const { return (size() == 0); }

  inline iterator       begin()       { return iterator(path_, 0); }
  inline const_iterator begin() const { return const_iterator(path_, 0); }
  inline iterator       end()         { return iterator(path_, size()); }
  inline const_iterator end() const   { return const_iterator(path_, size()); }

  inline reverse_iterator       rbegin()       { return reverse_iterator(end()); }
  inline reverse_iterator       rend()         { return reverse_iterator(begin()); }
  inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
  inline const_reverse_iterator rend()   const { return const_reverse_iterator(begin()); }

  const_reference  operator[](size_type i) const;
  inline reference operator[](size_type i) { return reference(path_, i); }

  inline reference       front()       { return reference(path_, 0); }
  inline const_reference front() const { return (*this)[0]; }
  inline reference       back()        { return reference(path_, size() - 1); }
  inline const_reference back()  const { return (*this)[size() - 1]; }
};

/** @relates Path::Nodes::const_iterator */
inline bool operator==(const Path::Nodes::const_iterator& a, const Path::Nodes::const_iterator& b)
  { return a.equal(b); }

/** @relates Path::Nodes::const_iterator */
inline bool operator!=(const Path::Nodes::const_iterator& a, const Path::Nodes::const_iterator& b)
  { return !a.equal(b); }

#ifndef DOXYGEN_SHOULD_SKIP_THIS
inline Path::Nodes Path::nodes()
  { return Path::Nodes(gobj()); }

inline const Path::Nodes Path::nodes() const
  { return Path::Nodes(const_cast<ClutterPath*>(gobj())); }
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Clutter


namespace Clutter
{

/** @relates Clutter::PathNode
 * @param lhs The left-hand side
 * @param rhs The right-hand side
 * @result The result
 */
bool operator==(const PathNode& lhs, const PathNode& rhs);

/** @relates Clutter::PathNode
 * @param lhs The left-hand side
 * @param rhs The right-hand side
 * @result The result
 */
bool operator!=(const PathNode& lhs, const PathNode& rhs);


} // namespace Clutter


namespace Glib
{

/** @relates Clutter::PathNode
 * @param object The C instance
 * @result A C++ instance that wraps this C instance.
 */
Clutter::PathNode& wrap(ClutterPathNode* object);

/** @relates Clutter::PathNode
 * @param object The C instance
 * @result A C++ instance that wraps this C instance.
 */
const Clutter::PathNode& wrap(const ClutterPathNode* object);

#ifndef DOXYGEN_SHOULD_SKIP_THIS
template <>
class Value<Clutter::PathNode> : public Glib::Value_Boxed<Clutter::PathNode>
{};
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Glib


namespace Glib
{
  /** A Glib::wrap() method for this object.
   * 
   * @param object The C instance.
   * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
   * @result A C++ instance that wraps this C instance.
   *
   * @relates Clutter::Path
   */
  Glib::RefPtr<Clutter::Path> wrap(ClutterPath* object, bool take_copy = false);
}


#endif /* _CLUTTERMM_PATH_H */

