<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
]>
<refentry id="chap-actions">
<refmeta>
<refentrytitle>The GTK Action Model</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>

<refnamediv>
<refname>The GTK Action Model</refname>
<refpurpose>
    How actions are used in GTK
</refpurpose>
</refnamediv>


  <refsect1 id="actions-overview">
    <title>Overview of actions in GTK</title>

  <para>
   This chapter describes in detail how GTK uses actions to connect
   activatable UI elements to callbacks. GTK inherits the underlying
   architecture of GAction and GMenu for describing abstract actions
   and menus from the GIO library.
  </para>

  <refsect2>
    <title>Basics about actions</title>

    <para>
     A GAction is essentially a way to tell the toolkit about a
     piece of functionality in your program, and to give it a name.
   </para>

   <para>
     Actions are purely functional. They do not contain any
     presentational information.
   </para>

   <para>
     An action has four pieces of information associated with it:
     <itemizedlist>
       <listitem><para>
         a name as an identifier (usually all-lowercase, untranslated
         English string)
       </para></listitem>
       <listitem><para>
         an enabled flag indicating if the action can be activated or
         not (like the "sensitive" property on widgets)
       </para></listitem>
       <listitem><para>
         an optional state value, for stateful actions (like a boolean
         for toggles)
       </para></listitem>
       <listitem><para>
         an optional parameter type, used when activating the action
       </para></listitem>
     </itemizedlist>
   </para>

   <para>
     An action supports two operations. You can activate it, which
     requires passing a parameter of the correct type
     And you can request to change the actions state (for stateful
     actions) to a new state value of the correct type.
   </para>

   <para>
     Here are some rules about an action:
     <itemizedlist>
       <listitem><para>
         the name is immutable (in the sense that it will never
         change) and it is never <link linkend="NULL:CAPS"><literal>NULL</literal></link>
       </para></listitem>
       <listitem><para>
         the enabled flag can change
       </para></listitem>
       <listitem><para>
         the parameter type is immutable
       </para></listitem>
       <listitem><para>
         the parameter type is optional: it can be <link linkend="NULL:CAPS"><literal>NULL</literal></link>
       </para></listitem>
       <listitem><para>
         if the parameter type is <link linkend="NULL:CAPS"><literal>NULL</literal></link> then action activation must
         be done without a parameter (ie: a <link linkend="NULL:CAPS"><literal>NULL</literal></link> GVariant pointer)
       </para></listitem>
       <listitem><para>
         if the parameter type is non-<link linkend="NULL:CAPS"><literal>NULL</literal></link> then the parameter must
         have this type
       </para></listitem>
       <listitem><para>
         the state can change, but it cannot change type
       </para></listitem>
       <listitem><para>
         if the action was stateful when it was created, it will
         always have a state and it will always have exactly the same
         type (such as boolean or string)
       </para></listitem>
       <listitem><para>
         if the action was stateless when it was created, it can never
         have a state
       </para></listitem>
       <listitem><para>
         you can only request state changes on stateful actions and it
         is only possible to request that the state change to a value
         of the same type as the existing state
       </para></listitem>
     </itemizedlist>
   </para>

   <para>
     An action does not have any sort of presentational information
     such as a label, an icon or a way of creating a widget from it.
   </para>

   </refsect2>

   <refsect2>
     <title>Action state and parameters</title>

     <para>
       Most actions in your application will be stateless actions with
       no parameters. These typically appear as menu items with no
       special decoration. An example is "quit".
     </para>

     <para>
       Stateful actions are used to represent an action which has a
       closely-associated state of some kind. A good example is a
       "fullscreen" action. For this case, you'd expect to see a
       checkmark next to the menu item when the fullscreen option
       is active. This is usually called a toggle action, and it has
       a boolean state. By convention, toggle actions have no parameter
       type for activation: activating the action always toggles the
       state.
     </para>

     <para>
       Another common case is to have an action representing a
       enumeration of possible values of a given type (typically
       string). This is often called a radio action and is usually
       represented in the user interface with radio buttons or radio
       menu items, or sometimes a combobox. A good example is
       "text-justify" with possible values "left", "center", and
       "right". By convention, these types of actions have a parameter
       type equal to their state type, and activating them with a
       particular parameter value is equivalent to changing their
       state to that value.
     </para>

     <para>
       This approach to handling radio buttons is different than many
       other action systems such as GtkAction. With GAction, there is
       only one action for "text-justify" and "left", "center" and
       "right" are possible states on that action. There are not three
       separate "justify-left", "justify-center" and "justify-right"
       actions.
     </para>

     <para>
       The final common type of action is a stateless action with a
       parameter. This is typically used for actions like
       "open-bookmark" where the parameter to the action would be
       the identifier of the bookmark to open.
     </para>

     <para>
       Because some types of actions cannot be invoked without a
       parameter, it is often important to specify a parameter when
       referring to the action from a place where it will be invoked
       (such as from a radio button that sets the state to a particular
       value or from a menu item that opens a specific bookmark). In
       these contexts, the value used for the action parameter is
       typically called the target of the action.
     </para>

     <para>
       Even though toggle actions have a state, they do not have a
       parameter. Therefore, a target value is not needed when
       referring to them — they will always be toggled on activation.
     </para>

     <para>
       Most APIs that allow using a GAction (such as GMenuModel and
       GtkActionable) allow use of detailed action names. This is a
       convenient way of specifying an action name and an action target
       with a single string.
     </para>

     <para>
       In the case that the action target is a string with no unusual
       characters (ie: only alpha-numeric, plus '-' and '.') then you
       can use a detailed action name of the form "justify::left" to
       specify the justify action with a target of left.
     </para>

     <para>
       In the case that the action target is not a string, or contains
       unusual characters, you can use the more general format
       "action-name(5)", where the "5" here is any valid text-format
       GVariant (ie: a string that can be parsed by <link linkend="g-variant-parse"><function>g_variant_parse()</function></link>).
       Another example is "open-bookmark('http://gnome.org/')".
     </para>

     <para>
       You can convert between detailed action names and split-out
       action names and target values using <link linkend="g-action-parse-detailed-name"><function>g_action_parse_detailed_name()</function></link>
       and <link linkend="g-action-print-detailed-name"><function>g_action_print_detailed_name()</function></link> but usually you will
       not need to. Most APIs will provide both ways of specifying
       actions with targets.
     </para>

   </refsect2>

   <refsect2>
     <title>Action scopes</title>

     <para>
       Actions are always scoped to a particular object on which they
       operate.
     </para>

     <para>
       In GTK, actions are typically scoped to either an application
       or a window, but any widget can have actions associated with it.
     </para>

     <para>
       Actions scoped to windows should be the actions that
       specifically impact that window. These are actions like
       "fullscreen" and "close", or in the case that a window contains
       a document, "save" and "print".
     </para>

     <para>
       Actions that impact the application as a whole rather than one
       specific window are scoped to the application. These are actions
       like "about" and "preferences".
     </para>

     <para>
       If a particular action is scoped to a window then it is scoped
       to a specific window. Another way of saying this: if your
       application has a "fullscreen" action that applies to windows
       and it has three windows, then it will have three fullscreen
       actions: one for each window.
     </para>

     <para>
       Having a separate action per-window allows for each window to
       have a separate state for each instance of the action as well
       as being able to control the enabled state of the action on a
       per-window basis.
     </para>

     <para>
       Actions are added to their relevant scope (application,
       window or widget) either using the GActionMap interface,
       or by using <link linkend="gtk-widget-insert-action-group"><function>gtk_widget_insert_action_group()</function></link>. Actions that
       will be the same for all instances of a widget class can
       be added globally using <link linkend="gtk-widget-class-install-action"><function>gtk_widget_class_install_action()</function></link>.
     </para>

  </refsect2>

  <refsect2>
    <title>Action groups and action maps</title>

    <para>
      Actions rarely occurs in isolation. It is common to have groups
      of related actions, which are represented by instances of the
      GActionGroup interface.
    </para>

    <para>
      Action maps are a variant of action groups that allow to change
      the name of the action as it is looked up. In GTK, the convention
      is to add a prefix to the action name to indicate the scope of
      the actions, such as "app." for the actions with application scope
      or "win." for those with window scope.
    </para>

    <para>
      When referring to actions on a GActionMap only the name of the
      action itself is used (ie: "quit", not "app.quit"). The
      "app.quit" form is only used when referring to actions from
      places like a GMenu or GtkActionable widget where the scope
      of the action is not already known.
    </para>

    <para>
      GtkApplication and GtkApplicationWindow implement the GActionMap
      interface, so you can just add actions directly to them. For
      other widgets, use <link linkend="gtk-widget-insert-action-group"><function>gtk_widget_insert_action_group()</function></link> to add
      actions to it.
    </para>

    <para>
      If you want to insert several actions at the same time, it is
      typically faster and easier to use GActionEntry.
    </para>

  </refsect2>

  <refsect2>
    <title>Connecting actions to widgets</title>

    <para>
      Any widget that implements the GtkActionable interface can
      be connected to an action just by setting the ::action-name
      property. If the action has a parameter, you will also need
      to set the ::action-target property.
      Widgets that implement GtkActionable include GtkSwitch, GtkButton,
      and their respective subclasses.
    </para>

    <para>
      Another way of obtaining widgets that are connected to actions
      is to create a menu using a GMenu menu model. GMenu provides an
      abstract way to describe typical menus: nested groups of items
      where each item can have a label, and icon, and an action.
    </para>

    <para>
      Typical uses of GMenu inside GTK are to set up an application
      menu or menubar with <link linkend="gtk-application-set-app-menu"><function>gtk_application_set_app_menu()</function></link> or
      <link linkend="gtk-application-set-menubar"><function>gtk_application_set_menubar()</function></link>. Another, maybe more common use
      is to create a popover for a menubutton, using
      <link linkend="gtk-menu-button-set-menu-model"><function>gtk_menu_button_set_menu_model()</function></link>.
    </para>

    <para>
      Unlike traditional menus, those created from menu models don't
      have keyboard accelerators associated with menu items. Instead,
      GtkApplication offers the <link linkend="gtk-application-set-accels-for-action"><function>gtk_application_set_accels_for_action()</function></link>
      API to associate keyboard shortcuts with actions.
    </para>
  </refsect2>

  <refsect2>
    <title>Activation</title>

    <para>
      When a widget with a connected action is activated, GTK finds
      the action to activate by walking up the widget hierarchy,
      looking for a matching action, ending up at the GtkApplication.
    </para>
  </refsect2>

  <refsect2>
    <title>Built-in Actions</title>

    <para>
      GTK uses actions for its own purposes in a number places. These
      built-in actions can sometimes be activated by applications, and
      you should avoid naming conflicts with them when creating your
      own actions.
      <variablelist>
        <varlistentry>
          <term>default.activate</term>
          <listitem><para>Activates the default widget in a context
             (typically a GtkWindow, GtkDialog or GtkPopover)
          </para></listitem>
        </varlistentry>
        <varlistentry>
          <term>clipboard.cut, clipboard.copy, clipboard.paste</term>
          <listitem><para>Clipboard operations on entries, text view
            and labels, typically used in the context menu
          </para></listitem>
        </varlistentry>
        <varlistentry>
          <term>selection.delete, selection.select-all</term>
          <listitem><para>Selection operations on entries, text view
            and labels
          </para></listitem>
        </varlistentry>
        <varlistentry>
          <term>color.select, color.customize</term>
          <listitem><para>Operations on colors in GtkColorChooserWidget.
            These actions are unusual in that they have the non-trivial
            parameter type (dddd).
          </para></listitem>
        </varlistentry>
      </variablelist>
    </para>

  </refsect2>

  </refsect1>
</refentry>
