/* Copyright (C) 2003 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 <gtkmm/widget.h>
#include <gtkmm/celllayout.h>
#include <gtkmm/treemodel.h>

_PINCLUDE(glibmm/private/object_p.h)

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

namespace Gtk
{
class GTKMM_API CellArea;
class GTKMM_API Entry;

/** Completion functionality for Gtk::Entry.
 *
 * Gtk::EntryCompletion is an auxiliary object to be used in conjunction with
 * Gtk::Entry to provide the completion functionality.
 *
 * It derives from Gtk::CellLayout, to allow the user to add extra cells to the Gtk::TreeView with completion matches.
 *
 * "Completion functionality" means that when the user modifies the text in the
 * entry, Gtk::EntryCompletion checks which rows in the model match the current
 * content of the entry, and displays a list of matches. By default, the
 * matching is done by comparing the entry text case-insensitively against
 * the text column of the model (see set_text_column()),
 * but this can be overridden with a custom match function (see set_match_func()).
 *
 * When the user selects a completion, the content of the entry is updated.
 * By default, the content of the entry is replaced by the text column of the
 * model, but this can be overridden by connecting to the match_selected signal
 * and updating the entry in the signal handler. Note that you should return true
 * from the signal handler to suppress the default behaviour.
 *
 * To add completion functionality to an entry, use Gtk::Entry::set_completion().
 *
 * @deprecated 4.10: GtkEntryCompletion will be removed in GTK 5.
 */
class GTKMM_API EntryCompletion
 : public Glib::Object,
   public Gtk::CellLayout,
   public Gtk::Buildable
{
  _CLASS_GOBJECT(EntryCompletion, GtkEntryCompletion, GTK_ENTRY_COMPLETION, Glib::Object, GObject, , , GTKMM_API)
  _IMPLEMENTS_INTERFACE(CellLayout)
  _IMPLEMENTS_INTERFACE(Buildable)

protected:
  _CTOR_DEFAULT()

public:
  _WRAP_CREATE()

  //Careful, this actually returns a GtkWidget*, so it might not always be a GtkEntry in future GTK+ versions.
  _WRAP_METHOD(Entry* get_entry(), gtk_entry_completion_get_entry)
  _WRAP_METHOD(const Entry* get_entry() const, gtk_entry_completion_get_entry)

  /** Sets the model for a %Gtk::EntryCompletion.
   * If @a completion 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: GtkEntryCompletion will be removed in GTK 5.
   *
   * @param model The `Gtk::TreeModel`.
   */
  _WRAP_METHOD(void set_model(const Glib::RefPtr<TreeModel>& model), gtk_entry_completion_set_model)
  _WRAP_METHOD(Glib::RefPtr<TreeModel> get_model(), gtk_entry_completion_get_model, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const TreeModel> get_model() const, gtk_entry_completion_get_model, refreturn, constversion)

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

  /// For example, bool on_match(const Glib::ustring& key, const TreeModel::const_iterator& iter);
  typedef sigc::slot<bool(const Glib::ustring&, const TreeModel::const_iterator&)> SlotMatch;

  void set_match_func(const SlotMatch& slot);
  _IGNORE(gtk_entry_completion_set_match_func)

  _WRAP_METHOD(void set_minimum_key_length(int length), gtk_entry_completion_set_minimum_key_length)
  _WRAP_METHOD(int get_minimum_key_length() const, gtk_entry_completion_get_minimum_key_length)
  _WRAP_METHOD(Glib::ustring compute_prefix(const Glib::ustring& key), gtk_entry_completion_compute_prefix)
  _WRAP_METHOD(void complete(), gtk_entry_completion_complete)

  _WRAP_METHOD(void insert_prefix(), gtk_entry_completion_insert_prefix)

  _WRAP_METHOD(void set_inline_completion(bool inline_completion = true), gtk_entry_completion_set_inline_completion)
  _WRAP_METHOD(bool get_inline_completion() const, gtk_entry_completion_get_inline_completion)
  _WRAP_METHOD(void set_inline_selection(bool inline_selection = true), gtk_entry_completion_set_inline_selection)
  _WRAP_METHOD(bool get_inline_selection() const, gtk_entry_completion_get_inline_selection)
  _WRAP_METHOD(void set_popup_completion(bool popup_completion = true), gtk_entry_completion_set_popup_completion)
  _WRAP_METHOD(bool get_popup_completion() const, gtk_entry_completion_get_popup_completion)

  _WRAP_METHOD(void set_popup_set_width(bool popup_set_width = true), gtk_entry_completion_set_popup_set_width)
  _WRAP_METHOD(bool get_popup_set_width() const, gtk_entry_completion_get_popup_set_width)

  _WRAP_METHOD(void set_popup_single_match(bool popup_single_match = true), gtk_entry_completion_set_popup_single_match)

  _WRAP_METHOD(bool get_popup_single_match() const, gtk_entry_completion_get_popup_single_match)

  /** Get the original text entered by the user that triggered
   * the completion or an empty string if there's no completion ongoing.
   *
   * Deprecated: 4.10: GtkEntryCompletion will be removed in GTK 5.
   *
   * @return The prefix for the current completion.
   */
  _WRAP_METHOD(Glib::ustring get_completion_prefix() const, gtk_entry_completion_get_completion_prefix)

  _WRAP_METHOD(void set_text_column(const TreeModelColumnBase& column), gtk_entry_completion_set_text_column)
  _WRAP_METHOD(void set_text_column(int column), gtk_entry_completion_set_text_column)
  _WRAP_METHOD(int get_text_column() const, gtk_entry_completion_get_text_column)

  //We completely hand-code these signals because we want to change how the parameters are wrapped,
  //because we need both the iter and the model to make the C++ iter.
  _IGNORE_SIGNAL(match_selected)
  _IGNORE_SIGNAL(cursor_on_match)

  /** Emitted when a match from the list is selected.
   * The default behaviour is to replace the contents of the
   * entry with the contents of the text column in the row
   * pointed to by @a iter.
   *
   * It is necessary to connect your signal handler <i>before</i>
   * the default one, which would otherwise return <tt>true</tt>,
   * a value which signifies that the signal has been handled,
   * thus preventing any other handler from being invoked.
   *
   * To do this, pass <tt>false</tt> to this signal proxy's
   * <tt>connect()</tt> method. For example:
   * <tt> completion->signal_match_selected().connect(sigc::mem_fun(*this, &YourClass::on_completion_match_selected), false); </tt>
   *
   * @param model The TreeModel containing the matches
   * @param iter A TreeModel::iterator positioned at the selected match
   * @result true if the signal has been handled
   *
   * @par Prototype:
   * <tt>bool %on_match_selected(const TreeModel::iterator& iter)</tt>
   */
  Glib::SignalProxy<bool(const TreeModel::iterator&)> signal_match_selected();

  /** Emitted when a match from the cursor is on a match
   * of the list. The default behaviour is to replace the contents
   * of the entry with the contents of the text column in the row
   * pointed to by @a iter.
   *
   * @param model The TreeModel containing the matches
   * @param iter A TreeModel::iterator positioned at the selected match
   * @result true if the signal has been handled
   *
   * @par Prototype:
   * <tt>bool %on_cursor_on_match(const TreeModel::iterator& iter)</tt>
   */
  Glib::SignalProxy<bool(const TreeModel::iterator&)> signal_cursor_on_match();

  // no_default_handler because GtkEntryCompletionClass is private.
#m4 _CONVERSION(`const char*',`const Glib::ustring&',__GCHARP_TO_USTRING)
  _WRAP_SIGNAL(bool insert_prefix(const Glib::ustring& prefix), insert_prefix, no_default_handler)
  _WRAP_SIGNAL(void no_matches(), no_matches, no_default_handler)

  _WRAP_PROPERTY("model", Glib::RefPtr<Gtk::TreeModel>)
  _WRAP_PROPERTY("minimum_key_length", int)
  _WRAP_PROPERTY("text_column", int)
  _WRAP_PROPERTY("inline_completion", bool)
  _WRAP_PROPERTY("popup_completion", bool)
  _WRAP_PROPERTY("popup_set_width", bool)
  _WRAP_PROPERTY("popup_single_match", bool)
  _WRAP_PROPERTY("inline-selection", bool)
  _WRAP_PROPERTY("cell-area", Glib::RefPtr<CellArea>)
};

} // namespace Gtk
