/* Copyright (C) 2020 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 <http://www.gnu.org/licenses/>.
 */

_CONFIGINCLUDE(gtkmmconfig.h)

#include <glibmm/object.h>
#include <giomm/listmodel.h>
#include <gtkmm/treelistrow.h>

_DEFS(gtkmm,gtk)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gtk
{

/** A list model that can create child models on demand.
 *
 * %Gtk::TreeListModel is a Gio::ListModel implementation that can expand rows
 * by creating new child list models on demand.
 *
 * @see Gio::ListModel
 * @ingroup ListView
 *
 * @newin{3,98}
 */
class GTKMM_API TreeListModel : public Glib::Object, public Gio::ListModel
{
  _CLASS_GOBJECT(TreeListModel, GtkTreeListModel, GTK_TREE_LIST_MODEL, Glib::Object, GObject, , , GTKMM_API)
  _IMPLEMENTS_INTERFACE(Gio::ListModel)
  _DO_NOT_DERIVE_GTYPE dnl// GtkTreeListModel is a final type
  _ABI_AS_WITH_DERIVED_GTYPE dnl// Remove when we can break ABI
  _STRUCT_NOT_HIDDEN

public:

  /** For instance:
   * Glib::RefPtr<Gio::ListModel> create_func(const Glib::RefPtr<Glib::ObjectBase>& item);
   *
   * Prototype of the function called to create new child models when
   * Gtk::TreeListRow::set_expanded() is called.
   *
   * This function can return <tt>nullptr</tt> to indicate that @a item is
   * guaranteed to be a leaf node and will never have children.
   * If it does not have children but may get children later, it should return
   * an empty model that is filled once children arrive.
   *
   * @param item The item that is being expanded.
   *
   * @return The model tracking the children of @a item or <tt>nullptr</tt> if
   * @a item can never have children.
   */
  using SlotCreateModel = sigc::slot<Glib::RefPtr<Gio::ListModel>(const Glib::RefPtr<Glib::ObjectBase>&)>;

protected:

  TreeListModel(const Glib::RefPtr<Gio::ListModel>& root, const SlotCreateModel& slot_create, bool passthrough = false, bool autoexpand = false);

public:

  /** Creates a new empty %Gtk::TreeListModel displaying @a root with
   * all rows collapsed.
   *
   * @param root The Gio::ListModel to use as root.
   * @param slot_create Slot to call to create the Gio::ListModel for
   * the children of an item.
   * @param passthrough <tt>true</tt> to pass through items from the models.
   * @param autoexpand <tt>true</tt> to set the autoexpand property and
   * expand the @a root model.
   */
  _WRAP_CREATE(const Glib::RefPtr<Gio::ListModel>& root, const SlotCreateModel& slot_create, bool passthrough = false, bool autoexpand = false)

  _WRAP_METHOD(Glib::RefPtr<Gio::ListModel> get_model(), gtk_tree_list_model_get_model, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gio::ListModel> get_model() const, gtk_tree_list_model_get_model, refreturn, constversion)
  _WRAP_METHOD(bool get_passthrough() const, gtk_tree_list_model_get_passthrough)
  _WRAP_METHOD(void set_autoexpand(bool autoexpand = true), gtk_tree_list_model_set_autoexpand)
  _WRAP_METHOD(bool get_autoexpand() const, gtk_tree_list_model_get_autoexpand)

  _WRAP_METHOD(Glib::RefPtr<TreeListRow> get_child_row(guint position), gtk_tree_list_model_get_child_row)
  _WRAP_METHOD(Glib::RefPtr<const TreeListRow> get_child_row(guint position) const, gtk_tree_list_model_get_child_row, constversion)
  _WRAP_METHOD(Glib::RefPtr<TreeListRow> get_row(guint position), gtk_tree_list_model_get_row)
  _WRAP_METHOD(Glib::RefPtr<const TreeListRow> get_row(guint position) const, gtk_tree_list_model_get_row, constversion)

  _WRAP_PROPERTY("autoexpand", bool)
  _WRAP_PROPERTY("item-type", GType)
  _WRAP_PROPERTY("model", Glib::RefPtr<Gio::ListModel>)
  _WRAP_PROPERTY("n-items", unsigned int)
  _WRAP_PROPERTY("passthrough", bool)
};

} // namespace Gtk
