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

/* iconview.h
 * 
 * Copyright (C) 1998-2004 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/container.h>
#include <gtkmm/treemodel.h>
#include <gtkmm/treepath.h>
#include <gtkmm/cellrenderer.h>
#include <gtkmm/tooltip.h>
_DEFS(gtkmm,gtk)
_PINCLUDE(gtkmm/private/container_p.h)

namespace Gtk
{

_WRAP_ENUM(IconViewDropPosition, GtkIconViewDropPosition)

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

/** The IconView provides an alternative view of a list model.
 * It displays the model as a grid of icons with labels. 
 * Like the TreeView, it allows the user to select one or multiple items 
 * (depending on the selection mode - see set_selection_mode()).
 * In addition to selection with the arrow keys, the IconView supports
 * rubberband selection, by dragging the pointer.
 *
 * @ingroup Widgets
 * @ingroup Containers
 */
class IconView : public Container
{
  _CLASS_GTKOBJECT(IconView, GtkIconView, GTK_ICON_VIEW, Gtk::Container, GtkContainer)
public:

  _CTOR_DEFAULT()
  _WRAP_CTOR(IconView(const Glib::RefPtr<TreeModel>& model), gtk_icon_view_new_with_model)


  _WRAP_METHOD(void set_model(const Glib::RefPtr<TreeModel>& model), gtk_icon_view_set_model)
  _WRAP_METHOD(Glib::RefPtr<TreeModel> get_model(), gtk_icon_view_get_model)
  _WRAP_METHOD(Glib::RefPtr<const TreeModel> get_model() const, gtk_icon_view_get_model, constversion)

  _WRAP_METHOD(void set_text_column(int column), gtk_icon_view_set_text_column)
  _WRAP_METHOD(void set_text_column(const TreeModelColumnBase& model_column), gtk_icon_view_set_text_column)
  _WRAP_METHOD(int get_text_column() const, gtk_icon_view_get_text_column)
  _WRAP_METHOD(void set_markup_column(int column), gtk_icon_view_set_markup_column)
  _WRAP_METHOD(void set_markup_column(const TreeModelColumnBase& column), gtk_icon_view_set_markup_column) 
  _WRAP_METHOD(int get_markup_column() const, gtk_icon_view_get_markup_column )
  _WRAP_METHOD(void set_pixbuf_column(int column), gtk_icon_view_set_pixbuf_column)
  _WRAP_METHOD(void set_pixbuf_column(const TreeModelColumnBase& column), gtk_icon_view_set_pixbuf_column)  
  _WRAP_METHOD(int get_pixbuf_column() const, gtk_icon_view_get_pixbuf_column)

  _WRAP_METHOD(void set_orientation(Orientation orientation), gtk_icon_view_set_orientation)
  _WRAP_METHOD(Orientation get_orientation() const, gtk_icon_view_get_orientation)

  _WRAP_METHOD(void set_columns(int columns), gtk_icon_view_set_columns)
  _WRAP_METHOD(int get_columns() const, gtk_icon_view_get_columns)
  _WRAP_METHOD(void set_item_width(int item_width), gtk_icon_view_set_item_width)
  _WRAP_METHOD(int get_icon_width() const, gtk_icon_view_get_item_width)
  _WRAP_METHOD(void set_spacing(int spacing), gtk_icon_view_set_spacing)
  _WRAP_METHOD(int get_spacing() const, gtk_icon_view_get_spacing)
  _WRAP_METHOD(void set_row_spacing(int row_spacing), gtk_icon_view_set_row_spacing)
  _WRAP_METHOD(gint get_row_spacing() const, gtk_icon_view_get_row_spacing)
  _WRAP_METHOD(void set_column_spacing(int column_spacing), gtk_icon_view_set_column_spacing)
  _WRAP_METHOD(int get_column_spacing() const, gtk_icon_view_get_column_spacing)

  _WRAP_METHOD(void set_margin(int margin), gtk_icon_view_set_margin)
  _WRAP_METHOD(int get_margin() const, gtk_icon_view_get_margin)

  _WRAP_METHOD(TreeModel::Path get_path_at_pos(int x, int y) const, gtk_icon_view_get_path_at_pos )


  /** Finds the path at the point (@a x, @a y), relative to widget coordinates.
   *
   * @param x The x position to be identified.
   * @param y The y position to be identified.
   * @param path The path.
   * @param cell The renderer responsible for the cell at (@a x, @a y).
   * 
   * @result true if an item exists at the specified position.
   *
   * @newin2p6
   */
  bool get_item_at_pos(int x, int y, TreeModel::Path& path, CellRenderer*& cell) const;

  /** Finds the path at the point (@a x, @a y), relative to widget coordinates.
   *
   * @param x The x position to be identified.
   * @param y The y position to be identified.
   * @param path The path.
   * 
   * @result true if an item exists at the specified position.
   *
   * @newin2p6
   */
  bool get_item_at_pos(int x, int y, TreeModel::Path& path) const;

  /** Finds the path at the point (@a x, @a y), relative to widget coordinates.
   *
   * @param x The x position to be identified.
   * @param y The y position to be identified.
   * @param path The path.
   * 
   * @result true if an item exists at the specified position.
   *
   * @newin2p6
   */
  bool get_item_at_pos(int x, int y, CellRenderer*& cell) const;
  _IGNORE(gtk_icon_view_get_item_at_pos)

  bool get_visible_range(TreeModel::Path& start_path, TreeModel::Path& end_path) const;
  _IGNORE(gtk_icon_view_get_visible_range)


  /** For instance, 
   * void on_foreach(const Gtk::TreeModel::Path& path);
   */
  typedef sigc::slot<void, const TreeModel::Path&> SlotForeach;

  /** Calls a function for each selected icon. Note that the model or
  * selection cannot be modified from within this function.
  *
  * @param slot The callback to call for each selected icon.
  */
  void selected_foreach(const SlotForeach& slot);
  _IGNORE(gtk_icon_view_selected_foreach)

//Default value?:
  _WRAP_METHOD(void set_selection_mode(SelectionMode mode), gtk_icon_view_set_selection_mode)
  _WRAP_METHOD(SelectionMode get_selection_mode() const, gtk_icon_view_get_selection_mode)
  _WRAP_METHOD(void select_path(const TreeModel::Path& path), gtk_icon_view_select_path)
  _WRAP_METHOD(void unselect_path(const TreeModel::Path& path), gtk_icon_view_unselect_path)
  _WRAP_METHOD(bool path_is_selected(const TreeModel::Path& path) const, gtk_icon_view_path_is_selected)


  #ifndef DOXYGEN_SHOULD_SKIP_THIS
  //TODO: I'm not sure about these to_*() functions. murrayc.
  struct TreePathTraits
  {
    typedef TreePath  CppType;
    typedef const GtkTreePath* CType;
    typedef GtkTreePath*    CTypeNonConst;

    static CType   to_c_type      (const CppType& obj) { return obj.gobj(); }
    static CType   to_c_type      (const CType&   obj) { return obj; }
    static CppType to_cpp_type    (const CType&   obj) { return CppType(const_cast<CTypeNonConst>(obj), true); }
    static void    release_c_type (const CType&)       {}
  };
  #endif //DOXYGEN_SHOULD_SKIP_THIS

  typedef Glib::ListHandle<TreePath, TreePathTraits> ArrayHandle_TreePaths;

  _CONVERSION(`GList*',`ArrayHandle_TreePaths',__FL2H_SHALLOW)
  _WRAP_METHOD(ArrayHandle_TreePaths get_selected_items() const, gtk_icon_view_get_selected_items)

  _WRAP_METHOD(void select_all(), gtk_icon_view_select_all)
  _WRAP_METHOD(void unselect_all(), gtk_icon_view_unselect_all)
  _WRAP_METHOD(void item_activated(const TreeModel::Path& path),  gtk_icon_view_item_activated)

  void set_cursor(const TreeModel::Path& path, CellRenderer& cell, bool start_editing);
  _IGNORE(gtk_icon_view_set_cursor)

  /** Fills in @a path and @a cell with the current cursor path and cell. 
   * If the cursor isn't currently set, then @a path will be empty.
   * If no cell currently has focus, then @a cell will be NULL.
   *
   * @param path The current cursor path.
   * @param cell The current focus cell.
   * @result true if the cursor is set.
   *
   * @newin2p8
   */
  bool get_cursor(TreeModel::Path& path, CellRenderer*& cell) const;

  /** Fills in @a path and @a cell with the current cursor path and cell. 
   * If the cursor isn't currently set, then @a path will be empty.
   * If no cell currently has focus, then @a cell will be NULL.
   *
   * @param path The current cursor path.
   * @result true if the cursor is set.
   *
   * @newin2p8
   */
  bool get_cursor(TreeModel::Path& path) const;

  /** Fills in @a path and @a cell with the current cursor path and cell. 
   * If the cursor isn't currently set, then @a path will be empty.
   * If no cell currently has focus, then @a cell will be NULL.
   *
   * @param cell The current focus cell.
   * @result true if the cursor is set.
   *
   * @newin2p8
   */
  bool get_cursor(CellRenderer*& cell) const;
  _IGNORE(gtk_icon_view_get_cursor)

  _WRAP_METHOD(void scroll_to_path(const TreeModel::Path& path, bool use_align, gfloat row_align, gfloat col_align), gtk_icon_view_scroll_to_path)

/* Drag-and-Drop support */
  /**
   * Turns the IconView into a drag source for automatic DND.
   *
   * @param targets Standard container of targets that the drag will support.
   * @param start_button_mask Mask of allowed buttons to start drag.
   * @param actions The bitmask of possible actions for a drag from this widget.
   */
  void enable_model_drag_source(const ArrayHandle_TargetEntry& targets,
                                Gdk::ModifierType start_button_mask = Gdk::MODIFIER_MASK,
                                Gdk::DragAction actions = Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
  _IGNORE(gtk_icon_view_enable_model_drag_source)

  /** Turns the IconView into a drop destination for automatic DND.
   *
   * @param targets The table of targets that the drag will support.
   * @param actions The bitmask of possible actions for a drag from this widget.
   */
  void enable_model_drag_dest(const ArrayHandle_TargetEntry& targets, Gdk::DragAction actions = Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
  _IGNORE(gtk_icon_view_enable_model_drag_dest)

  _WRAP_METHOD(void unset_model_drag_source(), gtk_icon_view_unset_model_drag_source)
  _WRAP_METHOD(void unset_model_drag_dest(), gtk_icon_view_unset_model_drag_dest)

  _WRAP_METHOD(void set_reorderable(bool reorderable = true), gtk_icon_view_set_reorderable)
  _WRAP_METHOD(bool get_reorderable() const, gtk_icon_view_get_reorderable)


/* These are useful to implement your own custom stuff. */
  //TODO: Discover what arguments are output arguments:
  _WRAP_METHOD(void set_drag_dest_item(const TreeModel::Path& path, IconViewDropPosition pos), gtk_icon_view_set_drag_dest_item)

  /** Gets information about the item that is highlighted for feedback.
   *
   * @param path The highlighted item.
   * @pos The drop position.
   *
   * @newin2p10
   */
  void get_drag_dest_item(TreeModel::Path& path, IconViewDropPosition& pos) const;

  /** Gets information about the item that is highlighted for feedback.
   *
   * @param path The highlighted item.
   *
   * @newin2p10
   */
  void get_drag_dest_item(TreeModel::Path& path) const;

  /** Gets information about the item that is highlighted for feedback.
   *
   * @pos The drop position.
   *
   * @newin2p10
   */
  void get_drag_dest_item(IconViewDropPosition& pos) const;
  _IGNORE(gtk_icon_view_get_drag_dest_item)

  /** Determines the destination item for a given position.
   *
   * @param drag_x The position to determine the destination item for.
   * @param drag_y the position to determine the destination item for.
   * @param path The path of the item.
   * @param pos: The drop position.
   * @result whether there is an item at the given position.
   *
   * @newin2p10
   */
  bool get_dest_item_at_pos(int drag_x, int drag_y, TreeModel::Path& path, IconViewDropPosition& pos) const;

  /** Determines the destination item for a given position.
   *
   * @param drag_x The position to determine the destination item for.
   * @param drag_y the position to determine the destination item for.
   * @param path The path of the item.
   * @result whether there is an item at the given position.
   *
   * @newin2p10
   */
  bool get_dest_item_at_pos(int drag_x, int drag_y, TreeModel::Path& path) const;

  /** Determines the destination item for a given position.
   * 
   * @param drag_x The position to determine the destination item for.
   * @param drag_y the position to determine the destination item for.
   * @param pos: The drop position.
   * @result whether there is an item at the given position.
   *
   * @newin2p10
   */
  bool get_dest_item_at_pos(int drag_x, int drag_y, IconViewDropPosition& pos) const;
  _IGNORE(gtk_icon_view_get_dest_item_at_pos)

  _WRAP_METHOD(Glib::RefPtr<Gdk::Pixmap> create_drag_icon( const TreeModel::Path& path), gtk_icon_view_create_drag_icon)

  _WRAP_METHOD(void convert_widget_to_bin_window_coords(int wx, int wy, int& bx, int& by) const, gtk_icon_view_convert_widget_to_bin_window_coords);

  _WRAP_METHOD(void set_tooltip_item(const Glib::RefPtr<Tooltip>& tooltip, const TreeModel::Path& path), gtk_icon_view_set_tooltip_item)
  _WRAP_METHOD(void set_tooltip_cell(const Glib::RefPtr<Tooltip>& tooltip, const TreeModel::Path& path, CellRenderer& cell), gtk_icon_view_set_tooltip_cell)

  /** Sets the tip area of @a tooltip to the area occupied by 
   * the item pointed to by @a path. See also Tooltip::set_tip_area().
   * 
   * @newin2p12
   * @param tooltip A Gtk::Tooltip.
   * @param path A Gtk::TreePath.
   */
  void set_tooltip_cell(const Glib::RefPtr<Tooltip>& tooltip, const TreeModel::Path& path);

  _IGNORE(gtk_tree_view_get_tooltip_context)

  /**
   * @param x: the x coordinate (relative to widget coordinates)
   * @param y: the y coordinate (relative to widget coordinates)
   * @param keyboard_tip: whether this is a keyboard tooltip or not
   * @param path: a reference to receive a Gtk::TreePath
   *
   * This function is supposed to be used in a Gtk::Widget::query-tooltip
   * signal handler for Gtk::IconView. The x, y and keyboard_tip values
   * which are received in the signal handler, should be passed to this
   * function without modification.
   *
   * The return value indicates whether there is an icon view item at the given
   * coordinates (true) or not (false) for mouse tooltips. For keyboard
   * tooltips the item returned will be the cursor item. When true, then the
   * path which has been provided will be set to point to
   * that row and the corresponding model. x and y will always be converted
   * to be relative to IconView's bin_window if keyboard_tooltip is false.
   *
   * Return value: whether or not the given tooltip context points to a item.
   *
   * @newin2p12
   */
  bool get_tooltip_context_path(int& x, int& y,
                                bool keyboard_tip,
                                TreeModel::Path& path);

  /**
   * @param x: the x coordinate (relative to widget coordinates)
   * @param y: the y coordinate (relative to widget coordinates)
   * @param keyboard_tip: whether this is a keyboard tooltip or not
   * @param iter: a pointer to receive a Gtk::TreeIter
   *
   * This function is supposed to be used in a Gtk::Widget::query-tooltip
   * signal handler for Gtk::IconView. The x, y and keyboard_tip values
   * which are received in the signal handler, should be passed to this
   * function without modification.
   *
   * The return value indicates whether there is an icon view item at the given
   * coordinates (true) or not (false) for mouse tooltips. For keyboard
   * tooltips the item returned will be the cursor item. When true, then the
   * iter which has been provided will be set to point to
   * that row and the corresponding model. x and y will always be converted
   * to be relative to IconView's bin_window if keyboard_tooltip is false.
   *
   * Return value: whether or not the given tooltip context points to a item.
   *
   * @newin2p12
   */
  bool get_tooltip_context_iter(int& x, int& y,
                                bool keyboard_tip,
                                Gtk::TreeModel::iterator& iter);

  _WRAP_METHOD(void set_tooltip_column(int column), gtk_icon_view_set_tooltip_column)
  _WRAP_METHOD(int get_tooltip_column() const, gtk_icon_view_get_tooltip_column)


  _WRAP_SIGNAL(void set_scroll_adjustments(Adjustment* hadjustment, Adjustment* vadjustment), set_scroll_adjustments) 
  _WRAP_SIGNAL(void item_activated(const TreeModel::Path& path), item_activated)
  _WRAP_SIGNAL(void selection_changed(), selection_changed)

  /* Key binding signals */
  _IGNORE_SIGNAL(select_all)
  _IGNORE_SIGNAL(unselect_all)
  _IGNORE_SIGNAL(select_cursor_item)
  _IGNORE_SIGNAL(toggle_cursor_item)
  _IGNORE_SIGNAL(move_cursor)
  _IGNORE_SIGNAL(activate_cursor_item)
  
  _WRAP_PROPERTY("pixbuf-column", int)
  _WRAP_PROPERTY("text-column", int)
  _WRAP_PROPERTY("markup-column", int)
  _WRAP_PROPERTY("selection-mode", SelectionMode)
  _WRAP_PROPERTY("orientation", Orientation)
  _WRAP_PROPERTY("model", Glib::RefPtr<TreeModel>)
  _WRAP_PROPERTY("columns", int)
  _WRAP_PROPERTY("item-width", int)
  _WRAP_PROPERTY("spacing", int)
  _WRAP_PROPERTY("row-spacing", int)
  _WRAP_PROPERTY("column-spacing", int)
  _WRAP_PROPERTY("margin", int)
};

} // namespace Gtk

