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

#include <glibmm.h>

/* $Id: treeiter.hg,v 1.34 2003/09/15 17:14:12 mxpxpod Exp $ */

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


#include <gtkmm/treemodelcolumn.h>
#include <gtkmmconfig.h>
#include <iterator>
#include <gtk/gtktreemodel.h> /* for GtkTreeIter */

GTKMM_USING_STD(forward_iterator_tag)


namespace Gtk
{

class TreeModel;
class TreeRow;
class TreeNodeChildren;

/**
 * @ingroup TreeView
 */
class TreeIterBase
{
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef TreeIterBase CppObjectType;
  typedef GtkTreeIter BaseObjectType;

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

  TreeIterBase();

  explicit TreeIterBase(const GtkTreeIter* gobject); // always takes a copy

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

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

protected:
  GtkTreeIter gobject_;

private:
  
  
  //A wrap() for TreeIterBase* wouldn't be very helpful.


};


// In order to offer STL-like iterator functionality, we cannot wrap
// GtkTreeIter directly.  Most GTK+ functions that operate on GtkTreeIter
// are virtual functions in GtkTreeModel.  Therefore, the C++ TreeIter
// must store a pointer to the Gtk::TreeModel to which it belongs.
//
// Another problem, which is much worse, is that the GTK+ tree iterator
// doesn't support the STL-style half-open interval [begin,end).  Instead,
// it uses a [first,last] interval, and functions return FALSE to indicate
// the end was reached.  Also, some functions accept a NULL GtkTreeIter*,
// which will be interpreted as the end() iterator.
//
// Most of the immense complexity in the Gtk::TreeIter implementation is
// needed for proper emulation of [begin,end) intervals.  Unfortunately,
// it's not even possible to encapsulate everything in the TreeIter
// class.  Almost all wrapper methods dealing with GtkTreeIter must be
// carefully implemented by hand.  TODO: document implementation details

//TODO: Implement a const_iterator too:
//danielk says that this ConstTreeIter class should return a ConstTreeRow, which would not allow operator=.

/** Typedefed as Gtk::TreeModel::iterator.
 * The Gtk::TreeModel iterator.
 * @ingroup TreeView
 */
class TreeIter : public TreeIterBase
{
public:
  typedef std::forward_iterator_tag iterator_category;
  typedef Gtk::TreeRow              value_type;
  typedef int                       difference_type;
  typedef const Gtk::TreeRow&       reference;
  typedef const Gtk::TreeRow*       pointer;

  TreeIter();

  TreeIter&      operator++();
  const TreeIter operator++(int);

  inline reference operator*()  const;
  inline pointer   operator->() const;

  bool equal(const TreeIter& other) const;

  //TODO_API: Add a virtual Model method to use the various GTK+ _iter_is_valid() functions, depending on the model.
  //instead of the slightly hacky way that we test for validity now. murrayc/danielk.
  operator bool() const;

#ifndef DOXYGEN_SHOULD_SKIP_THIS

  explicit TreeIter(TreeModel* model); // used in TreeModel methods
  TreeIter(GtkTreeModel* model, const GtkTreeIter* iter); // used by signal proxies

  void set_model_refptr(const Glib::RefPtr<TreeModel>& model);
  void set_model_gobject(GtkTreeModel* model);
  GtkTreeModel* get_model_gobject() const;

  void setup_end_iterator(const TreeIter& last_valid);

  const GtkTreeIter* get_gobject_if_not_end() const
    { return (!is_end_) ? &gobject_ : 0; }

  const GtkTreeIter* get_parent_gobject_if_end() const
    { return (is_end_ && gobject_.stamp) ? &gobject_ : 0; }

protected:

  // Yes, using a simple TreeModel* rather than Glib::RefPtr<TreeModel>
  // violates the general policy.  But Gtk::TreeIter should have a trivial
  // copy constructor and assignment operator, i.e. it must contain only
  // POD (plain old data).
  //
  // Gtk::TreeIter is copied a lot, particularly often as return value from
  // methods.  Postfix ++ must return by value, and STL algorithms usually
  // pass iterators by value, too.  With a RefPtr<> as member data, copying
  // would no longer be trivial, and even cause frequent calls to reference()
  // and unreference().  That usually doesn't matter much for GUI stuff, but
  // Gtk::TreeModel is used as a generic container.  Imagine a for-loop that
  // checks whether iter != children.end() on each iteration.

  TreeModel* model_;
  bool       is_end_;

  friend class Gtk::TreeRow;
  friend class Gtk::TreeNodeChildren;

#endif /* DOXYGEN_SHOULD_SKIP_THIS */
};

/** @relates Gtk::TreeIter */
inline bool operator==(const TreeIter& lhs, const TreeIter& rhs)
  { return lhs.equal(rhs); }

/** @relates Gtk::TreeIter */
inline bool operator!=(const TreeIter& lhs, const TreeIter& rhs)
  { return !lhs.equal(rhs); }


template <class ColumnType>
class TreeValueProxy
{
public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  inline TreeValueProxy(const TreeRow& row, const TreeModelColumn<ColumnType>& column);
#endif

  inline TreeValueProxy<ColumnType>& operator=(const ColumnType& data);
  inline operator ColumnType() const;

private:
  const TreeRow&                      row_;
  const TreeModelColumn<ColumnType>&  column_;

  // no copy assignment
  TreeValueProxy<ColumnType>& operator=(const TreeValueProxy<ColumnType>&);
};


/** Typedefed as TreeModel::Row.
 * Dereference a TreeModel::iterator to get the Row.
 * You can use a const TreeModel::Row& for any parameter that takes a const TreeModel::iterator&.
 * @ingroup TreeView
 */
class TreeRow : public TreeIter //We use public inheritance so that we can cast from a TreeRow to a TreeIter.
{
public:
  template <class ColumnType> inline
  TreeValueProxy<ColumnType> operator[](const TreeModelColumn<ColumnType>& column) const;

  template <class ColumnType>
  void set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data) const;

  /** Use set_value(const TreeModelColumn<>& column, const ColumnType& data) unless
   * you do not know the column type at compile-time.
   */
  template <class ColumnType>
  void set_value(int column, const ColumnType& data) const;

  template <class ColumnType>
  ColumnType get_value(const TreeModelColumn<ColumnType>& column) const;

  template <class ColumnType>
  void get_value(int column, ColumnType& data) const;

  const TreeNodeChildren& children() const;
  TreeIter parent() const;

  operator bool() const;

  GtkTreeIter*       gobj()       { return TreeIter::gobj(); }
  const GtkTreeIter* gobj() const { return TreeIter::gobj(); }

private:
  // Forwarders to Gtk::TreeModel virtual methods.
  void set_value_impl(int column, const Glib::ValueBase& value) const;
  void get_value_impl(int column, Glib::ValueBase& value) const;
};


/** typdefed as TreeModel::Children.
 * Virtual container of TreeModel::Row items.
 * @ingroup TreeView
 */
//TODO: make inheritance public
class TreeNodeChildren : private TreeIter
{
public:
  typedef Gtk::TreeRow  value_type;
  typedef unsigned int  size_type;
  typedef int           difference_type;
  typedef Gtk::TreeIter iterator;
  typedef Gtk::TreeIter const_iterator;

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

  value_type operator[](size_type index) const;

  size_type size() const;
  bool empty() const;
  operator bool() const { return !empty(); }

#ifndef DOXYGEN_SHOULD_SKIP_THIS

  explicit TreeNodeChildren(TreeModel* model)
    : TreeIter(model) {}

  const GtkTreeIter* get_parent_gobject() const
    { return (gobject_.stamp != 0) ? &gobject_ : 0; }

#endif /* DOXYGEN_SHOULD_SKIP_THIS */
};


#ifndef DOXYGEN_SHOULD_SKIP_THIS

/**** Gtk::TreeIter ********************************************************/

inline
TreeIter::reference TreeIter::operator*() const
{
  return static_cast<const TreeRow&>(*this);
}

inline
TreeIter::pointer TreeIter::operator->() const
{
  return static_cast<const TreeRow*>(this);
}


/**** Gtk::TreeValueProxy<> ************************************************/

template <class ColumnType> inline
TreeValueProxy<ColumnType>::TreeValueProxy(const TreeRow& row, const TreeModelColumn<ColumnType>& column)
:
  row_    (row),
  column_ (column)
{}

template <class ColumnType> inline
TreeValueProxy<ColumnType>& TreeValueProxy<ColumnType>::operator=(const ColumnType& data)
{
  row_.set_value(column_, data);
  return *this;
}

template <class ColumnType> inline
TreeValueProxy<ColumnType>::operator ColumnType() const
{
  return row_.get_value(column_);
}


/**** Gtk::TreeRow *********************************************************/

template <class ColumnType> inline
TreeValueProxy<ColumnType> TreeRow::operator[](const TreeModelColumn<ColumnType>& column) const
{
  return TreeValueProxy<ColumnType>(*this, column);
}

template <class ColumnType>
void TreeRow::set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data) const
{
  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;

  ValueType value;
  value.init(column.type());

  value.set(data);
  this->set_value_impl(column.index(), value);
}

template <class ColumnType>
void TreeRow::set_value(int column, const ColumnType& data) const
{
  //This could fail at run-time, because the wrong ColumnType might be used.
  //It's only for dynamically generated model columns.

  typedef typename Gtk::TreeModelColumn<ColumnType> type_cppcolumn;
  typedef typename type_cppcolumn::ValueType ValueType;

  ValueType value;
  value.init(ValueType::value_type());

  value.set(data);
  this->set_value_impl(column, value);
}

template <class ColumnType>
ColumnType TreeRow::get_value(const TreeModelColumn<ColumnType>& column) const
{
  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;

  ValueType value;
  this->get_value_impl(column.index(), value);

  return value.get();
}

template <class ColumnType>
void TreeRow::get_value(int column, ColumnType& data) const
{
  //This could fail at run-time, because the wrong ColumnType might be used.
  //It's only for dynamically generated model columns.

  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;

  ValueType value;
  this->get_value_impl(column, value);

  data = value.get();
}

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Gtk


namespace Glib
{

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

} // namespace Glib

#endif /* _GTKMM_TREEITER_H */

