/* 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, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#m4 _PUSH(SECTION_CC_PRE_INCLUDES)
#undef GTK_DISABLE_DEPRECATED
#m4 _POP()
_CONFIGINCLUDE(gtkmmconfig.h)

#include <gtkmm/widget.h>
#include <gtkmm/accelgroup.h>
#include <gtkmm/stockid.h>
#include <giomm/icon.h>

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

namespace Gtk
{

class ActionGroup;
class Menu;
class MenuItem;
class ToolItem;
class Image;

/** An action which can be triggered by a menu or toolbar item.
 *
 * Actions represent operations that the user can perform, along with
 * some information about how it should be presented in the user interface.
 * Each action provides methods to create icons, menu items and toolbar
 * items representing itself.
 *
 * As well as the callback that is called when the action is activated,
 * the following is also associated with the action:
 *
 *  - a name (not translated, for path lookup)
 *  - a label (translated, for display)
 *  - an accelerator
 *  - whether the label indicates a stock id
 *  - a tooltip (optional, translated)
 *  - a toolbar label (optional, shorter than label)
 *
 * The action will also have some state information:
 *
 *  - visible (shown/hidden)
 *  - sensitive (enabled/disabled)
 *
 * Apart from regular actions, there are toggle actions,
 * which can be toggled between two states and radio actions,
 * of which only one in a group can be in the "active" state.
 * Other actions can be implemented as Gtk::Action subclasses.
 *
 * Each action can have one or more proxy menu item, toolbar button or other proxy widgets.
 * Proxies mirror the state of the action (text label, tooltip, icon, visible, sensitive, etc), and should change when the action's state changes. When the proxy is activated, it should activate its action.
 */
class Action : public Glib::Object
{
  _CLASS_GOBJECT(Action, GtkAction, GTK_ACTION, Glib::Object, GObject)

protected:
  /** Creates an empty action. */
  _CTOR_DEFAULT

  /** Creates an action with a stock ID.
   * The stock ID is used to set a default icon, text and accelerator for the
   * action.
   *
   * @param name     A unique name for the action.
   * @param stock_id The stock icon to display in widgets representing the
   *                 action.
   * @param label    The label displayed in menu items and on buttons.
   * @param tooltip  A tooltip for the action.
   */
  explicit Action(const Glib::ustring& name, const StockID& stock_id = StockID(), const Glib::ustring& label = Glib::ustring(), const Glib::ustring& tooltip = Glib::ustring());

  /** Creates an action with an icon name.
   * The action's icon will reflect the specified icon name in the user's
   * icon theme.
   *
   * @param name      A unique name for the action.
   * @param icon_name An IconTheme icon name used for widgets representing the
   *                  action.
   * @param label     The label displayed in menu items and on buttons.
   * @param tooltip   A tooltip for the action.
   */
  explicit Action(const Glib::ustring& name, const Glib::ustring& icon_name, const Glib::ustring& label = Glib::ustring(), const Glib::ustring& tooltip = Glib::ustring());

public:
  //Note that gtk_action_new() does not allow name to be NULL, which suggests that we should not have a default constructor,
  //but it's OK to set the name later:
  _WRAP_CREATE()

  /** Creates an action.
   *
   * @param name    A unique name for the action.
   * @param label   The label displayed in menu items and on buttons.
   * @param tooltip A tooltip for the action.
   *
   * @return A new Action.
   */
  static Glib::RefPtr<Action> create(const Glib::ustring& name, const Glib::ustring& label = Glib::ustring(), const Glib::ustring& tooltip = Glib::ustring());

  /** Creates an action with a stock ID.
   * The stock ID is used to set a default icon, text and accelerator for the
   * action.
   *
   * @param name     A unique name for the action.
   * @param stock_id The stock icon to display in widgets representing the
   *                 action.
   * @param label    The label displayed in menu items and on buttons.
   * @param tooltip  A tooltip for the action.
   *
   * @return A new Action.
   */
  static Glib::RefPtr<Action> create(const Glib::ustring& name, const Gtk::StockID& stock_id, const Glib::ustring& label = Glib::ustring(), const Glib::ustring& tooltip = Glib::ustring());

  /** Create an action with an icon name.
   * The action's icon will reflect the specified icon name in the user's
   * icon theme.
   *
   * @param name      A unique name for the action.
   * @param icon_name An IconTheme icon name used for widgets representing the
   *                  action.
   * @param label     The label displayed in menu items and on buttons.
   * @param tooltip   A tooltip for the action.
   *
   * @return A new Action.
   */
  static Glib::RefPtr<Action> create_with_icon_name(const Glib::ustring& name, const Glib::ustring& icon_name, const Glib::ustring& label, const Glib::ustring& tooltip);

  _WRAP_METHOD(Glib::ustring get_name() const, gtk_action_get_name)

  _WRAP_METHOD(bool is_sensitive() const, gtk_action_is_sensitive)
  _WRAP_METHOD(bool get_sensitive() const, gtk_action_get_sensitive)

  _WRAP_METHOD(void set_sensitive(bool sensitive = true), gtk_action_set_sensitive)

  _WRAP_METHOD(bool is_visible() const, gtk_action_is_visible)
  _WRAP_METHOD(bool get_visible() const, gtk_action_get_visible)
  _WRAP_METHOD(void set_visible(bool visible = true), gtk_action_set_visible)

  _WRAP_METHOD(void activate(), gtk_action_activate)
  _WRAP_METHOD(Image* create_icon(IconSize icon_size), gtk_action_create_icon)
  _WRAP_METHOD(MenuItem* create_menu_item(), gtk_action_create_menu_item)
  _WRAP_METHOD(ToolItem* create_tool_item(), gtk_action_create_tool_item)
  _WRAP_METHOD(Menu* create_menu(), gtk_action_create_menu)

  //TODO: Deprecate these when we can derive the appropriate widgets from Activatable, when we can break ABI.
  _WRAP_METHOD(void connect_proxy(Widget& proxy), gtk_action_connect_proxy)
  _WRAP_METHOD(void disconnect_proxy(Widget& proxy), gtk_action_disconnect_proxy)

#m4 dnl // This isn't in convert_gtk.m4, and the default behaviour is wrong.
#m4 _CONVERSION(`GSList*', `Glib::SListHandle<Widget*>', `$2($3, Glib::OWNERSHIP_NONE)')
#m4 _CONVERSION(`GSList*', `Glib::SListHandle<const Widget*>', `$2($3, Glib::OWNERSHIP_NONE)')

  _WRAP_METHOD(Glib::SListHandle<Widget*> get_proxies(), gtk_action_get_proxies)
  _WRAP_METHOD(Glib::SListHandle<const Widget*> get_proxies() const, gtk_action_get_proxies)

  _WRAP_METHOD(void connect_accelerator(), gtk_action_connect_accelerator)
  _WRAP_METHOD(void disconnect_accelerator(), gtk_action_disconnect_accelerator)

  _WRAP_METHOD(Glib::ustring get_accel_path() const, gtk_action_get_accel_path)

  /// For instance, void on_activate();
  typedef sigc::slot<void> SlotActivate;

  /** The "activate" signal is emitted when the action is activated.
   */
  _WRAP_SIGNAL(void activate(), "activate")

  //Used by AccelGroup:
  _WRAP_METHOD(void set_accel_path(const Glib::ustring& accel_path), gtk_action_set_accel_path)
  _WRAP_METHOD(void set_accel_group(const Glib::RefPtr<AccelGroup>& accel_group), gtk_action_set_accel_group)

  _WRAP_METHOD(void set_label(const Glib::ustring& label), gtk_action_set_label)
  _WRAP_METHOD(Glib::ustring get_label() const, gtk_action_get_label)
  _WRAP_METHOD(void set_short_label(const Glib::ustring& short_label), gtk_action_set_short_label)
  _WRAP_METHOD(Glib::ustring get_short_label() const, gtk_action_get_short_label)
  _WRAP_METHOD(void set_tooltip(const Glib::ustring& tooltip), gtk_action_set_tooltip)
  _WRAP_METHOD(Glib::ustring get_tooltip() const, gtk_action_get_tooltip)
  _WRAP_METHOD(void set_stock_id(const StockID& stock_id), gtk_action_set_stock_id)
  _WRAP_METHOD(StockID get_stock_id() const, gtk_action_get_stock_id)
  _WRAP_METHOD(void set_gicon(const Glib::RefPtr<Gio::Icon>& icon), gtk_action_set_gicon)
  _WRAP_METHOD(Glib::RefPtr<Gio::Icon> get_gicon(), gtk_action_get_gicon, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gio::Icon> get_gicon() const, gtk_action_get_gicon, refreturn, constversion)
  _WRAP_METHOD(void set_icon_name(const Glib::ustring& icon_name), gtk_action_set_icon_name)
  _WRAP_METHOD(Glib::ustring get_icon_name() const, gtk_action_get_icon_name)
  _WRAP_METHOD(void set_visible_horizontal(bool visible_horizontal = true), gtk_action_set_visible_horizontal)
  _WRAP_METHOD(bool get_visible_horizontal() const, gtk_action_get_visible_horizontal)
  _WRAP_METHOD(void set_visible_vertical(bool visible_vertical = true), gtk_action_set_visible_vertical)
  _WRAP_METHOD(bool get_visible_vertical() const, gtk_action_get_visible_vertical)
  _WRAP_METHOD(void set_is_important(bool is_important = true), gtk_action_set_is_important)
  _WRAP_METHOD(bool get_is_important() const, gtk_action_get_is_important)

  _WRAP_METHOD(void set_always_show_image(bool always_show = true), gtk_action_set_always_show_image)
  _WRAP_METHOD(bool get_always_show_image() const, gtk_action_get_always_show_image)

  _WRAP_METHOD(void block_activate(), gtk_action_block_activate)
  _WRAP_METHOD(void unblock_activate(), gtk_action_unblock_activate)

  //gtk_action_get_accel_closure() is too C-specific:
  _IGNORE(gtk_action_get_accel_closure)

  _WRAP_PROPERTY("name", Glib::ustring)
  _WRAP_PROPERTY("label", Glib::ustring)
  _WRAP_PROPERTY("short_label", Glib::ustring)
  _WRAP_PROPERTY("tooltip", Glib::ustring)
  _WRAP_PROPERTY("stock_id", StockID)
  _WRAP_PROPERTY("gicon", Glib::RefPtr<Gio::Icon>)
  _WRAP_PROPERTY("icon_name", Glib::ustring)
  _WRAP_PROPERTY("visible_horizontal", bool)
  _WRAP_PROPERTY("visible_vertical", bool)
  _WRAP_PROPERTY("visible_overflown", bool)
  _WRAP_PROPERTY("is_important", bool)
  _WRAP_PROPERTY("hide_if_empty", bool)
  _WRAP_PROPERTY("sensitive", bool)
  _WRAP_PROPERTY("visible", bool)
  _WRAP_PROPERTY("action_group", Glib::RefPtr<ActionGroup>)
  _WRAP_PROPERTY("always-show-image", bool)

protected:
  //For use by child actions:
  //TODO: Deprecate these when we can derive the appropriate widgets from Activatable, when we can break ABI.
  _WRAP_METHOD(void block_activate_from(Widget& proxy), gtk_action_block_activate_from)
  _WRAP_METHOD(void unblock_activate_from(Widget& proxy), gtk_action_unblock_activate_from)

protected:
  //Widget-creation routines:
  _WRAP_VFUNC(Widget* create_menu_item(), "create_menu_item")
  _WRAP_VFUNC(Widget* create_tool_item(), "create_tool_item")
  _WRAP_VFUNC(void connect_proxy(Widget* proxy), "connect_proxy")
  _WRAP_VFUNC(void disconnect_proxy(Widget* proxy), "disconnect_proxy")
};

} // namespace Gtk
