/* 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/interface.h>
#include <glibmm/value.h>

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

#ifndef DOXYGEN_SHOULD_SKIP_THIS
extern "C"
{
typedef struct _GtkAccessibleInterface GtkAccessibleInterface;
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

namespace Gtk
{
class ATContext;

/** %Accessible interface.
 *
 * %Gtk::Accessible provides an interface for describing a UI element, like a
 * Gtk::Widget, in a way that can be consumed by Assistive Technologies, or
 * “AT”. Every accessible implementation has:
 *
 *  - a “role”, represented by a value of the Gtk::Accessible::Role enumeration
 *  - an “attribute”, represented by a set of Gtk::Accessible::State,
 *    Gtk::Accessible::Property and Gtk::Accessible::Relation values
 *
 * The role cannot be changed after instantiating a %Gtk::Accessible
 * implementation.
 *
 * The attributes are updated every time a UI element's state changes in a way that
 * should be reflected by assistive technologies. For instance, if a Gtk::Widget
 * visibility changes, the Gtk::Accessible::State::HIDDEN state will also change
 * to reflect Gtk::Widget::property_visible().
 *
 * @newin{3,98}
 */
class GTKMM_API Accessible : public Glib::Interface
{
  _CLASS_INTERFACE(Accessible, GtkAccessible, GTK_ACCESSIBLE, GtkAccessibleInterface, , , GTKMM_API)

public:
  _WRAP_ENUM(Role, GtkAccessibleRole, decl_prefix GTKMM_API)
  _WRAP_ENUM(State, GtkAccessibleState, decl_prefix GTKMM_API)
  _WRAP_ENUM(Property, GtkAccessibleProperty, decl_prefix GTKMM_API)
  _WRAP_ENUM(Relation, GtkAccessibleRelation, decl_prefix GTKMM_API)
  _WRAP_ENUM(PlatformState, GtkAccessiblePlatformState, decl_prefix GTKMM_API)
  _WRAP_ENUM(AnnouncementPriority, GtkAccessibleAnnouncementPriority, decl_prefix GTKMM_API)

  _WRAP_METHOD(Glib::RefPtr<ATContext> get_at_context(),
    gtk_accessible_get_at_context, refreturn, newin "4,10")
  _WRAP_METHOD(Glib::RefPtr<const ATContext> get_at_context() const,
    gtk_accessible_get_at_context, refreturn, constversion, newin "4,10")

  _WRAP_METHOD(bool get_platform_state(PlatformState state) const,
    gtk_accessible_get_platform_state)
  _WRAP_METHOD(void update_platform_state(PlatformState state),
    gtk_accessible_update_platform_state)
  _WRAP_METHOD(Glib::RefPtr<Accessible> get_accessible_parent(),
    gtk_accessible_get_accessible_parent, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Accessible> get_accessible_parent() const,
    gtk_accessible_get_accessible_parent, refreturn, constversion)
  _WRAP_METHOD(void set_accessible_parent(const Glib::RefPtr<Accessible>& parent,
    const Glib::RefPtr<Accessible>& next_sibling), gtk_accessible_set_accessible_parent)

  _WRAP_METHOD(Glib::RefPtr<Accessible> get_first_accessible_child(),
    gtk_accessible_get_first_accessible_child, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Accessible> get_first_accessible_child() const,
    gtk_accessible_get_first_accessible_child, refreturn, constversion)

  _WRAP_METHOD(Glib::RefPtr<Accessible> get_next_accessible_sibling(),
    gtk_accessible_get_next_accessible_sibling, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Accessible> get_next_accessible_sibling() const,
    gtk_accessible_get_next_accessible_sibling, refreturn, constversion)
  _WRAP_METHOD(void update_next_accessible_sibling(const Glib::RefPtr<Accessible>& new_sibling),
    gtk_accessible_update_next_accessible_sibling)

  _WRAP_METHOD(bool get_bounds(int& x, int& y, int& width, int& height) const,
    gtk_accessible_get_bounds)
  _WRAP_METHOD(Glib::ustring get_accessible_id() const, gtk_accessible_get_accessible_id)
  _WRAP_METHOD(Role get_accessible_role() const, gtk_accessible_get_accessible_role)

  _IGNORE(gtk_accessible_update_state, gtk_accessible_update_property,
    gtk_accessible_update_relation, gtk_accessible_update_state_value,
    gtk_accessible_update_property_value, gtk_accessible_update_relation_value)

  /** Updates an accessible state.
   *
   * This function should be called by Gtk::Widget types whenever an accessible
   * state change must be communicated to assistive technologies.
   *
   * @param state A Gtk::Accessible::State.
   * @param value A Glib::ValueBase.
   */
  void update_state(State state, const Glib::ValueBase& value);

  /** Updates an accessible property.
   *
   * This function should be called by Gtk::Widget types whenever an accessible
   * property change must be communicated to assistive technologies.
   *
   * @param property A Gtk::Accessible::Property.
   * @param value A Glib::ValueBase.
   */
  void update_property(Property property, const Glib::ValueBase& value);

  /** Updates an accessible relation.
   *
   * This function should be called by Gtk::Widget types whenever an accessible
   * relation change must be communicated to assistive technologies.
   *
   * @param relation A Gtk::Accessible::Relation.
   * @param value A Glib::ValueBase.
   */
  void update_relation(Relation relation, const Glib::ValueBase& value);

  _WRAP_METHOD(void reset_state(State state), gtk_accessible_reset_state)
  _WRAP_METHOD(void reset_property(Property property), gtk_accessible_reset_property)
  _WRAP_METHOD(void reset_relation(Relation relation), gtk_accessible_reset_relation)

  _WRAP_METHOD(void announce(const Glib::ustring& message, AnnouncementPriority priority),
    gtk_accessible_announce)

  _WRAP_PROPERTY("accessible-role", Role)

  //TODO: Add vfuncs, when we can break ABI
};

} // namespace Gtk
