/* 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 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, see <https://www.gnu.org/licenses/>.
 */

_DEFS(gtkmm,gtk)
_CONFIGINCLUDE(gtkmmconfig.h)
_IS_DEPRECATED // The entire file is deprecated.

#include <vector>
#include <gtkmm/widget.h>
#include <gtkmm/treemodel.h>
#include <gtkmm/treepath.h>
#include <gtkmm/celllayout.h>
#include <gtkmm/cellarea.h>
#include <gtkmm/cellrenderer.h>
#include <gtkmm/scrollable.h>
#include <gtkmm/tooltip.h>

_PINCLUDE(gtkmm/private/widget_p.h)

#m4 _PUSH(SECTION_CC_PRE_INCLUDES)
#undef GTK_DISABLE_DEPRECATED
#define GDK_DISABLE_DEPRECATION_WARNINGS 1
#m4 _POP()

namespace Gtk
{

/** 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
 * @deprecated 4.10: Use Gtk::GridView instead.
 */
class GTKMM_API IconView
 : public Widget,
   public CellLayout,
   public Scrollable
{
  _CLASS_GTKOBJECT(IconView, GtkIconView, GTK_ICON_VIEW, Gtk::Widget, GtkWidget, , , GTKMM_API)
  _IMPLEMENTS_INTERFACE(CellLayout)
  _IMPLEMENTS_INTERFACE(Scrollable)

public:
  _WRAP_ENUM(DropPosition, GtkIconViewDropPosition, decl_prefix GTKMM_API)

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

  /** Sets the model for a %Gtk::IconView.
   * If the @a icon_view already has a model set, it will remove
   * it before setting the new model. Use unset_model() to unset the old model.
   *
   * Deprecated: 4.10: Use Gtk::GridView instead
   *
   * @param model The 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, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const TreeModel> get_model() const, gtk_icon_view_get_model, refreturn, constversion)

  /** Remove the model from the IconView.
   *
   * @see set_model().
   */
  void unset_model();

  _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_item_orientation(Orientation orientation), gtk_icon_view_set_item_orientation)
  _WRAP_METHOD(Orientation get_item_orientation() const, gtk_icon_view_get_item_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(int 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(void set_item_padding(int item_padding), gtk_icon_view_set_item_padding)
  _WRAP_METHOD(int get_item_padding() const, gtk_icon_view_get_item_padding)

  _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[out] path The path.
   * @param[out] cell The renderer responsible for the cell at (@a x, @a y).
   * @result true if an item exists at the specified position.
   */
  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[out] path The path.
   * @result true if an item exists at the specified position.
   */
  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[out] cell The renderer responsible for the cell at (@a x, @a y).
   * @result true if an item exists at the specified position.
   */
  bool get_item_at_pos(int x, int y, CellRenderer*& cell) const;
  _IGNORE(gtk_icon_view_get_item_at_pos)

  /** Sets @a start_path and @a end_path to be the first and last visible path.
   * Note that there may be invisible paths in between.
   *
   * @param[out] start_path Return location for start of region.
   * @param[out] end_path Return location for end of region.
   * @result <tt>true</tt> if valid paths were placed in @a start_path and @a end_path.
   */
  bool get_visible_range(TreeModel::Path& start_path, TreeModel::Path& end_path) const;
  _IGNORE(gtk_icon_view_get_visible_range)

  _WRAP_METHOD(void set_activate_on_single_click(bool single = true), gtk_icon_view_set_activate_on_single_click)
  _WRAP_METHOD(bool get_activate_on_single_click() const, gtk_icon_view_get_activate_on_single_click)

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

  /** 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)

  _WRAP_METHOD(int get_item_row(const TreeModel::Path& path) const, gtk_icon_view_get_item_row)
  _WRAP_METHOD(int get_item_column(const TreeModel::Path& path) const, gtk_icon_view_get_item_column)

#m4 _CONVERSION(`GList*',`std::vector<TreePath>',`Glib::ListHandler<TreePath, TreePathTraits>::list_to_vector($3, Glib::OWNERSHIP_DEEP)')
  _WRAP_METHOD(std::vector<TreePath> 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)

  _WRAP_METHOD(void set_cursor(const TreeModel::Path& path, CellRenderer& cell{?}, bool start_editing), 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 nullptr.
   *
   * @param[out] path The current cursor path.
   * @param[out] cell The current focus cell.
   * @result true if the cursor is set.
   */
  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 nullptr.
   *
   * @param[out] path The current cursor path.
   * @result true if the cursor is set.
   */
  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 nullptr.
   *
   * @param[out] cell The current focus cell.
   * @result true if the cursor is set.
   */
  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, float row_align, float col_align), gtk_icon_view_scroll_to_path)

/* Drag-and-Drop support */
  // Gdk::ContentFormats is an immutable object. It can be declared const
  // in input parameters. No one can change it.

  _WRAP_METHOD(void enable_model_drag_source(const Glib::RefPtr<const Gdk::ContentFormats>& formats{.},
     Gdk::ModifierType start_button_mask{.} = static_cast<Gdk::ModifierType>(GDK_MODIFIER_MASK),
     Gdk::DragAction actions{.} = Gdk::DragAction::COPY | Gdk::DragAction::MOVE),
     gtk_icon_view_enable_model_drag_source)

  _WRAP_METHOD(void enable_model_drag_dest(
    const Glib::RefPtr<const Gdk::ContentFormats>& formats,
    Gdk::DragAction actions = Gdk::DragAction::COPY | Gdk::DragAction::MOVE),
    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. */
  _WRAP_METHOD(void set_drag_dest_item(const TreeModel::Path& path, DropPosition pos), gtk_icon_view_set_drag_dest_item)

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

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

  /** Gets information about the item that is highlighted for feedback.
   *
   * @param[out] pos The drop position.
   */
  void get_drag_dest_item(DropPosition& 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[out] path The path of the item.
   * @param[out] pos The drop position.
   * @result Whether there is an item at the given position.
   */
  bool get_dest_item_at_pos(int drag_x, int drag_y, TreeModel::Path& path, DropPosition& 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[out] path The path of the item.
   * @result Whether there is an item at the given position.
   */
  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[out] pos The drop position.
   * @result Whether there is an item at the given position.
   */
  bool get_dest_item_at_pos(int drag_x, int drag_y, DropPosition& pos) const;
  _IGNORE(gtk_icon_view_get_dest_item_at_pos)

  // create_drag_icon() is const because it returns a newly created Gdk::Paintable.
  _WRAP_METHOD(Glib::RefPtr<Gdk::Paintable> create_drag_icon(const TreeModel::Path& path) const, gtk_icon_view_create_drag_icon)

#m4 _INITIALIZATION(`Gdk::Rectangle&',`GdkRectangle', `$3 = Glib::wrap(&($4))')
  _WRAP_METHOD(bool get_cell_rect(const TreeModel::Path& path, const CellRenderer& cell{?}, Gdk::Rectangle& rect{.>>}) const, gtk_icon_view_get_cell_rect)

  _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().
   *
   * @param tooltip A Gtk::Tooltip.
   * @param path A Gtk::TreePath.
   */
  void set_tooltip_cell(const Glib::RefPtr<Tooltip>& tooltip, const TreeModel::Path& path);

  /** 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
   * @a path which has been provided will be set to point to
   * that row and the corresponding model.
   *
   * @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[out] path A reference to receive a Gtk::TreePath
   * @result Whether or not the given tooltip context points to an item.
   */
  bool get_tooltip_context_path(int x, int y,
                                bool keyboard_tip,
                                TreeModel::Path& path);

  /** 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
   * @a iter which has been provided will be set to point to
   * that row and the corresponding model.
   *
   * @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[out] iter A reference to receive a Gtk::TreeModel::iterator
   * @result Whether or not the given tooltip context points to an item.
   */
  bool get_tooltip_context_iter(int x, int y,
                                bool keyboard_tip,
                                Gtk::TreeModel::iterator& iter);
  _IGNORE(gtk_icon_view_get_tooltip_context)

  _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)

  // no_default_handler because GtkIconViewClass is private.
  _WRAP_SIGNAL(void item_activated(const TreeModel::Path& path), item_activated, no_default_handler)
  _WRAP_SIGNAL(void selection_changed(), selection_changed, no_default_handler)

  /* 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("item-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)
  _WRAP_PROPERTY("reorderable", int)
  _WRAP_PROPERTY("tooltip-column", int)
  _WRAP_PROPERTY("item-padding", int)
  _WRAP_PROPERTY("cell-area", Glib::RefPtr<CellArea>)
  _WRAP_PROPERTY("activate-on-single-click", bool)
};

} // namespace Gtk
