/* $Id: treeviewcolumn.hg,v 1.16 2006/07/08 16:31:38 murrayc Exp $ */

/* Copyright(C) 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/object.h>
#include <gtkmm/treeiter.h>
#include <gtkmm/widget.h>
#include <gdkmm/window.h>
#include <gtkmm/treemodel.h>
#include <glibmm/listhandle.h>
#include <gtkmm/cellrenderer_generation.h>
_DEFS(gtkmm,gtk)
_PINCLUDE(gtkmm/private/object_p.h)


namespace Gtk
{

_CC_INCLUDE(gtk/gtktypebuiltins.h)
_WRAP_ENUM(TreeViewColumnSizing, GtkTreeViewColumnSizing)


// We use GTKMM_API here because gcc needs the extra help on win32 , even 
// when using --export-all and auto-import. 
// See http://bugzilla.gnome.org/show_bug.cgi?id=309030.

//TODO: This should derive+implement from CellLayout when we can break ABI.

/** Typedefed as Gtk::TreeView::Column.
 * This is a visible column in a Gtk::TreeView widget. It determines the geometry, type.
 *
 * @ingroup TreeView
*/
class GTKMM_API TreeViewColumn : public Gtk::Object
{
  _CLASS_GTKOBJECT(TreeViewColumn, GtkTreeViewColumn, GTK_TREE_VIEW_COLUMN, Gtk::Object, GtkObject)
  _IGNORE(gtk_tree_view_column_set_cell_data_func)
public:
  typedef TreeViewColumn Column;

  _CTOR_DEFAULT()

  explicit TreeViewColumn(const Glib::ustring& title);
  TreeViewColumn(const Glib::ustring& title, CellRenderer& cell);

  /** Create a default view column for the given model column type.
   */
  template<class T_ModelColumnType>
  TreeViewColumn(const Glib::ustring& title, const TreeModelColumn<T_ModelColumnType>& column);

  _WRAP_METHOD(void pack_start(CellRenderer& cell, bool expand = true), gtk_tree_view_column_pack_start)
  _WRAP_METHOD(void pack_end(CellRenderer& cell, bool expand = true), gtk_tree_view_column_pack_end)

  /** Creates an appropriate CellRenderer for the @a column, and packs that cell into the beginning of the column.
   * If @a expand  is <tt>false</tt>, then
   * the cell is allocated no more space than it needs. Any unused space is divided
   * evenly between cells for which @a expand is <tt>true</tt>.
   *
   * You can use get_first_cell_renderer() or get_cell_renderers() to access the generated CellRenderer.
   *
   * @param column The model column that will be rendered by the view cell.
   * @param expand <tt>true</tt> if the cell is to be given extra space allocated to the view column.
   */
  template<class T_ModelColumnType>
  void pack_start(const TreeModelColumn<T_ModelColumnType>& column, bool expand = true);

  /** Creates an appropriate CellRenderer for the @a column, and packs that cell at the end of the column.
   * If @a expand  is <tt>false</tt>, then
   * the cell is allocated no more space than it needs. Any unused space is divided
   * evenly between cells for which @a expand is <tt>true</tt>.
   *
   * You can use get_first_cell_renderer() or get_cell_renderers() to access the generated CellRenderer.
   *
   * @param column The model column that will be rendered by the view cell.
   * @param expand <tt>true</tt> if the cell is to be given extra space allocated to the view column.
   */
  template<class T_ModelColumnType>
  void pack_end(const TreeModelColumn<T_ModelColumnType>& column, bool expand = true);

  _WRAP_METHOD(void clear(), gtk_tree_view_column_clear)

  /** Gets the CellRenderer for the column.
    * You should dynamic_cast<> to the expected derived CellRenderer type.
    * This assumes that the TreeViewColumn contains only one CellRenderer.
    */
  CellRenderer* get_first_cell_renderer();

  /** Gets the CellRenderer for the column.
    * You should dynamic_cast<> to the expected derived CellRenderer type.
    * This assumes that the TreeViewColumn contains only one CellRenderer.
    */
  const CellRenderer* get_first_cell_renderer() const;

  _WRAP_METHOD(Glib::ListHandle<CellRenderer*> get_cell_renderers(), gtk_tree_view_column_get_cell_renderers)
  _WRAP_METHOD(Glib::ListHandle<const CellRenderer*> get_cell_renderers() const, gtk_tree_view_column_get_cell_renderers)

  _WRAP_METHOD(void add_attribute(CellRenderer& cell_renderer, const Glib::ustring& attribute, int column),
               gtk_tree_view_column_add_attribute)

#ifdef GLIBMM_PROPERTIES_ENABLED
  void add_attribute(const Glib::PropertyProxy_Base& property, const TreeModelColumnBase& column);
#endif

  void add_attribute(Gtk::CellRenderer& cell, const Glib::ustring& property_name, const TreeModelColumnBase& column);
  _IGNORE(gtk_tree_view_column_set_attributes)

  /** Associate a view CellRenderer with a model column, so that the CellRenderer renders the data in the model column.
   *
   * @param renderer The view cell renderer which will render the model column.
   * @param column The model column to be renderered by this view.
   */
  void set_renderer(Gtk::CellRenderer& renderer, const TreeModelColumnBase& column);

 // _WRAP_METHOD(void set_attributes(CellRenderer& cell_renderer, ...), )

  /** For instance,
   * void on_cell_data(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter);
   *
   * This function is used instead of the standard attributes mapping for setting the column value, and should set the
   * value of the column's cell renderer as appropriate.
   */
  typedef sigc::slot<void, CellRenderer*, const Gtk::TreeModel::iterator&> SlotCellData;

  /** Sets the slot callback to use for the column.
   * This callback function is used instead of the standard attributes mapping for setting the column value, and should set the
   * value of the column's cell renderer as appropriate.
   *
   * See also unset_cell_data_func().
   *
   * @param cell_renderer A Gtk::CellRenderer
   * @param slot The callback slot to use. Create this with sigc::mem_fun(), or sigc::ptr_fun().
   */  
  void set_cell_data_func(CellRenderer& cell_renderer, const SlotCellData& slot);

  /** Removes a previously set callback slot. See set_cell_data_func().
   */ 
  void unset_cell_data_func(CellRenderer& cell_renderer);

  _WRAP_METHOD(void clear_attributes(CellRenderer& cell_renderer), gtk_tree_view_column_clear_attributes)
  _WRAP_METHOD(void set_spacing(int spacing), gtk_tree_view_column_set_spacing)
  _WRAP_METHOD(int get_spacing() const, gtk_tree_view_column_get_spacing)
  _WRAP_METHOD(void set_visible(bool visible = true), gtk_tree_view_column_set_visible)
  _WRAP_METHOD(bool get_visible() const, gtk_tree_view_column_get_visible)
  _WRAP_METHOD(void set_resizable(bool resizable = true), gtk_tree_view_column_set_resizable)
  _WRAP_METHOD(bool get_resizable() const, gtk_tree_view_column_get_resizable)
  _WRAP_METHOD(void set_sizing(TreeViewColumnSizing type), gtk_tree_view_column_set_sizing)
  _WRAP_METHOD(TreeViewColumnSizing get_sizing(), gtk_tree_view_column_get_sizing)
  _WRAP_METHOD(int get_width() const, gtk_tree_view_column_get_width)
  _WRAP_METHOD(int get_fixed_width() const, gtk_tree_view_column_get_fixed_width)
  _WRAP_METHOD(void set_fixed_width(int fixed_width), gtk_tree_view_column_set_fixed_width)
  _WRAP_METHOD(void set_min_width(int min_width), gtk_tree_view_column_set_min_width)
  _WRAP_METHOD(int get_min_width() const, gtk_tree_view_column_get_min_width)
  _WRAP_METHOD(void set_max_width(int max_width), gtk_tree_view_column_set_max_width)
  _WRAP_METHOD(int get_max_width() const, gtk_tree_view_column_get_max_width)
  _WRAP_METHOD(void clicked(), gtk_tree_view_column_clicked)

  _WRAP_METHOD(void set_title(const Glib::ustring& title), gtk_tree_view_column_set_title)
  _WRAP_METHOD(Glib::ustring get_title() const, gtk_tree_view_column_get_title)

  _WRAP_METHOD(void set_expand(bool expand = true), gtk_tree_view_column_set_expand)
  _WRAP_METHOD(bool get_expand() const, gtk_tree_view_column_get_expand)

  _WRAP_METHOD(void set_clickable(bool clickable = true), gtk_tree_view_column_set_clickable)
  _WRAP_METHOD(bool get_clickable() const, gtk_tree_view_column_get_clickable)
  _WRAP_METHOD(void set_widget(Gtk::Widget& widget), gtk_tree_view_column_set_widget)
  _WRAP_METHOD(Widget* get_widget(), gtk_tree_view_column_get_widget)
  _WRAP_METHOD(const Widget* get_widget() const, gtk_tree_view_column_get_widget)

  _WRAP_METHOD(void set_alignment(float xalign), gtk_tree_view_column_set_alignment)
  _WRAP_METHOD(void set_alignment(AlignmentEnum xalign), gtk_tree_view_column_set_alignment)

  _WRAP_METHOD(float get_alignment() const, gtk_tree_view_column_get_alignment)
  _WRAP_METHOD(void set_reorderable(bool reorderable = true), gtk_tree_view_column_set_reorderable)
  _WRAP_METHOD(bool get_reorderable() const, gtk_tree_view_column_get_reorderable)

  _WRAP_METHOD(void set_sort_column(const TreeModelColumnBase& sort_column_id), gtk_tree_view_column_set_sort_column_id)
  _WRAP_METHOD(void set_sort_column(int sort_column_id), gtk_tree_view_column_set_sort_column_id)

  _DEPRECATE_IFDEF_START
  /** @deprecated Use set_sort_column() instead.
   */
  void set_sort_column_id(const TreeModelColumnBase& sort_column_id);

  /** @deprecated Use set_sort_column() instead.
   */
  void set_sort_column_id(int sort_column_id);
  _DEPRECATE_IFDEF_END

  _WRAP_METHOD(int get_sort_column_id() const, gtk_tree_view_column_get_sort_column_id)
  _WRAP_METHOD(void set_sort_indicator(bool setting), gtk_tree_view_column_set_sort_indicator)
  _WRAP_METHOD(bool get_sort_indicator() const, gtk_tree_view_column_get_sort_indicator)
  _WRAP_METHOD(void set_sort_order(SortType order), gtk_tree_view_column_set_sort_order)
  _WRAP_METHOD(SortType get_sort_order() const, gtk_tree_view_column_get_sort_order)


  _WRAP_METHOD(void cell_set_cell_data(const Glib::RefPtr<TreeModel>& tree_model, const TreeModel::iterator& iter, bool is_expander, bool is_expanded), gtk_tree_view_column_cell_set_cell_data)
  _WRAP_METHOD(void cell_get_size(Gdk::Rectangle& cell_area, int& x_offset, int& y_offset, int& width, int& height) const, gtk_tree_view_column_cell_get_size)
  _WRAP_METHOD(bool cell_is_visible() const, gtk_tree_view_column_cell_is_visible)
  _WRAP_METHOD(void focus_cell(CellRenderer& cell), gtk_tree_view_column_focus_cell)

  _WRAP_METHOD(bool get_cell_position(const CellRenderer& cell_renderer, int& start_pos, int& width) const, gtk_tree_view_column_cell_get_position)
  _WRAP_METHOD(void queue_resize(), gtk_tree_view_column_queue_resize)

  _WRAP_SIGNAL(void clicked(), "clicked")

  _WRAP_PROPERTY("visible", bool)
  _WRAP_PROPERTY("width", int)
  _WRAP_PROPERTY("sizing", TreeViewColumnSizing)
  _WRAP_PROPERTY("fixed-width", int)
  _WRAP_PROPERTY("min-width", int)
  _WRAP_PROPERTY("max-width", int)
  _WRAP_PROPERTY("title", Glib::ustring)
  _WRAP_PROPERTY("expand", bool)
  _WRAP_PROPERTY("clickable", bool)
  _WRAP_PROPERTY("widget", Widget*)
  _WRAP_PROPERTY("alignment", float)
  _WRAP_PROPERTY("reorderable", bool)
  _WRAP_PROPERTY("sort-indicator", bool)
  _WRAP_PROPERTY("sort-order", SortType)

#ifndef DOXYGEN_SHOULD_SKIP_THIS
private:
  // Only necessary because of the templated ctor, see below.
  static const Glib::Class& class_init_();
#endif //DOXYGEN_SHOULD_SKIP_THIS
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS

template<class T_ModelColumnType> inline
void TreeViewColumn::pack_start(const TreeModelColumn<T_ModelColumnType>& column, bool expand)
{
  //Generate appropriate Renderer for the column:
  CellRenderer* pCellRenderer = manage( CellRenderer_Generation::generate_cellrenderer<T_ModelColumnType>() );

  //Use the renderer:
  pack_start(*pCellRenderer, expand);
  set_renderer(*pCellRenderer, column);
}

template<class T_ModelColumnType> inline
void TreeViewColumn::pack_end(const TreeModelColumn<T_ModelColumnType>& column, bool expand)
{
  //Generate appropriate Renderer for the column:
  CellRenderer* pCellRenderer= manage( CellRenderer_Generation::generate_cellrenderer<T_ModelColumnType>() );

  //Use the renderer:
  pack_end(*pCellRenderer, expand);
  set_renderer(*pCellRenderer, column);
}


template <class T_ModelColumnType> inline
TreeViewColumn::TreeViewColumn(const Glib::ustring& title,
                               const TreeModelColumn<T_ModelColumnType>& column)
:
  Glib::ObjectBase(0), // not (yet) a custom class
  Gtk::Object(Glib::ConstructParams(class_init_(), "title", title.c_str(), (char*) 0))
{
  pack_start(column, true /* expand */);
}



#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Gtk

