// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* $Id: iconview.ccg,v 1.7 2006/05/11 11:40:24 murrayc Exp $ */

/* Copyright 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/adjustment.h> 
#include <gtk/gtkiconview.h>
#include <gtk/gtktreemodel.h>
#include <gtk/gtktreeview.h>
#include <gtk/gtk.h>

namespace //anonymous namespace
{

static void proxy_foreach_callback(GtkIconView* /* icon_view */, GtkTreePath* path, void* data)
{
  typedef Gtk::IconView::SlotForeach SlotType;
  SlotType& slot = *static_cast<SlotType*>(data);

  #ifdef GLIBMM_EXCEPTIONS_ENABLED
  try
  {
  #endif //GLIBMM_EXCEPTIONS_ENABLED
    slot(Gtk::TreeModel::Path(path, true));
  #ifdef GLIBMM_EXCEPTIONS_ENABLED
  }
  catch(...)
  {
    Glib::exception_handlers_invoke();
  }
  #endif //GLIBMM_EXCEPTIONS_ENABLED
}

} //anonymous namespace


namespace Gtk
{

//Allow the generated code to work without the prefix:
typedef IconView::ArrayHandle_TreePaths ArrayHandle_TreePaths;

void IconView::selected_foreach(const SlotForeach& slot)
{
  SlotForeach slot_copy(slot);
  gtk_icon_view_selected_foreach(const_cast<GtkIconView*>(gobj()), &proxy_foreach_callback, &slot_copy);
}

bool IconView::get_item_at_pos(int x, int y, TreeModel::Path& path, CellRenderer*& cell) const
{
  GtkTreePath* cpath = 0;
  GtkCellRenderer* ccell = 0;
  bool result = gtk_icon_view_get_item_at_pos(const_cast<GtkIconView*>(gobj()), x, y, &cpath, &ccell);

  path = Glib::wrap(cpath); //Don't take copy because the gtk_icon_view_get_item_at_pos documentation says we should free this.
  cell = Glib::wrap(ccell);
  return result;
}

bool IconView::get_item_at_pos(int x, int y, TreeModel::Path& path) const
{
  GtkTreePath* cpath = 0;
  bool result = gtk_icon_view_get_item_at_pos(const_cast<GtkIconView*>(gobj()), x, y, &cpath, 0);

  path = Glib::wrap(cpath); //Don't take copy because the gtk_icon_view_get_item_at_pos documentation says we should free this.
  return result;
}

bool IconView::get_item_at_pos(int x, int y, CellRenderer*& cell) const
{
  GtkCellRenderer* ccell = 0;
  bool result = gtk_icon_view_get_item_at_pos(const_cast<GtkIconView*>(gobj()), x, y, 0, &ccell);

  cell = Glib::wrap(ccell);
  return result;
}

bool IconView::get_visible_range(TreeModel::Path& start_path, TreeModel::Path& end_path) const
{
  GtkTreePath* cstart_path = 0;
  GtkTreePath* cend_path = 0;
  bool result = gtk_icon_view_get_visible_range(const_cast<GtkIconView*>(gobj()), &cstart_path, &cend_path);

  start_path = Glib::wrap(cstart_path); //Don't take copy because the gtk_icon_view_get_visible_range documentation says we should free this.
  end_path = Glib::wrap(cend_path); //Don't take copy because the gtk_icon_view_get_visible_range documentation says we should free this.
  return result;
}

  _IGNORE(gtk_icon_view_get_visible_range)

bool IconView::get_cursor(TreeModel::Path& path, CellRenderer*& cell) const
{
  GtkTreePath* cpath = 0;
  GtkCellRenderer* ccell = 0;
  bool result = gtk_icon_view_get_cursor(const_cast<GtkIconView*>(gobj()), &cpath, &ccell);

  path = Glib::wrap(cpath); //Don't take copy because the gtk_icon_view_get_cursor documentation says we should free this.
  cell = Glib::wrap(ccell);
  return result;
}

bool IconView::get_cursor(TreeModel::Path& path) const
{
  GtkTreePath* cpath = 0;
  bool result = gtk_icon_view_get_cursor(const_cast<GtkIconView*>(gobj()), &cpath, 0);

  path = Glib::wrap(cpath); //Don't take copy because the gtk_icon_view_get_cursor documentation says we should free this.
  return result;
}

bool IconView::get_cursor(CellRenderer*& cell) const
{
  GtkCellRenderer* ccell = 0;
  bool result = gtk_icon_view_get_cursor(const_cast<GtkIconView*>(gobj()), 0, &ccell);

  cell = Glib::wrap(ccell);
  return result;
}

void IconView::get_drag_dest_item(TreeModel::Path& path, IconViewDropPosition& pos) const
{
  GtkTreePath* cpath = 0;
  gtk_icon_view_get_drag_dest_item(const_cast<GtkIconView*>(gobj()), &cpath, (GtkIconViewDropPosition*)(&pos));
  if(cpath)
    path = Gtk::TreeModel::Path(cpath, true /* make_a_copy */);
}

void IconView::get_drag_dest_item(TreeModel::Path& path) const
{
  GtkTreePath* cpath = 0;
  gtk_icon_view_get_drag_dest_item(const_cast<GtkIconView*>(gobj()), &cpath, NULL);
  if(cpath)
    path = Gtk::TreeModel::Path(cpath, true /* make_a_copy */);
}

void IconView::get_drag_dest_item(IconViewDropPosition& pos) const
{
   gtk_icon_view_get_drag_dest_item(const_cast<GtkIconView*>(gobj()), NULL, (GtkIconViewDropPosition*)(&pos));
}


bool IconView::get_dest_item_at_pos(int drag_x, int drag_y, TreeModel::Path& path, IconViewDropPosition& pos) const
{
  GtkTreePath* cpath = 0;
  const bool result = gtk_icon_view_get_dest_item_at_pos(const_cast<GtkIconView*>(gobj()), drag_x, drag_y, &cpath, (GtkIconViewDropPosition*)(&pos));
  if(cpath)
    path = Gtk::TreeModel::Path(cpath, true /* make_a_copy */);

  return result;
}

bool IconView::get_dest_item_at_pos(int drag_x, int drag_y, TreeModel::Path& path) const
{
  GtkTreePath* cpath = 0;
  const bool result = gtk_icon_view_get_dest_item_at_pos(const_cast<GtkIconView*>(gobj()), drag_x, drag_y, &cpath, NULL);
  if(cpath)
    path = Gtk::TreeModel::Path(cpath, true /* make_a_copy */);

  return result;
}

bool IconView::get_dest_item_at_pos(int drag_x, int drag_y, IconViewDropPosition& pos) const
{
  return gtk_icon_view_get_dest_item_at_pos(const_cast<GtkIconView*>(gobj()), drag_x, drag_y, NULL, (GtkIconViewDropPosition*)(&pos));
}


void IconView::enable_model_drag_source(const ArrayHandle_TargetEntry& targets, Gdk::ModifierType start_button_mask, Gdk::DragAction actions)
{
  gtk_icon_view_enable_model_drag_source(gobj(), (GdkModifierType)start_button_mask, targets.data(), targets.size(), (GdkDragAction)actions);
}


void  IconView::enable_model_drag_dest(const ArrayHandle_TargetEntry& targets, Gdk::DragAction actions)
{
  gtk_icon_view_enable_model_drag_dest(gobj(), targets.data(), targets.size(), (GdkDragAction)actions);
}

bool
IconView::get_tooltip_context_path(int& x, int& y,
                                   bool keyboard_tip,
                                   TreeModel::Path& path)
{
  //It's cleaner to use a temporary C++ object and get a C pointer to it,
  //because GtkTreePath is a simple struct, not a GtkObject, so
  //gtk_tree_path_new() would be necessary. markoa.
  TreeModel::Path tmp_path;
  GtkTreePath* cpath = tmp_path.gobj();

  gboolean result =
    gtk_icon_view_get_tooltip_context(gobj(),
                                      &x, &y,
                                      keyboard_tip,
                                      0,
                                      &cpath,
                                      0);

  path = Glib::wrap(cpath, false /* take_copy=false */);

  return result;
}

bool
IconView::get_tooltip_context_iter(int& x, int& y,
                                   bool keyboard_tip,
                                   Gtk::TreeModel::iterator& iter)
{
  GtkTreeIter src_iter;

  gboolean result =
    gtk_icon_view_get_tooltip_context(gobj(),
                                      &x, &y,
                                      keyboard_tip,
                                      0,
                                      0,
                                      &src_iter);

  iter = TreeIter(gtk_icon_view_get_model(this->gobj()), &src_iter);

  return result;
}

} // namespace Gtk

