<chapter 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 GMe:u for describing abstract actions
    and menus from the GIO library.
  </para>
  <sect1>
    <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:
    </para>
    <itemizedlist spacing="compact">
      <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 <quote>sensitive</quote> 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>
      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:
    </para>
    <itemizedlist spacing="compact">
      <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>
      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>
  </sect1>
  <sect1>
    <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 <quote>quit</quote>.
    </para>
    <para>
      Stateful actions are used to represent an action which has a
      closely-associated state of some kind. A good example is a
      <quote>fullscreen</quote> action. For this case, you would 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
      <quote>text-justify</quote> with possible values
      <quote>left</quote>, <quote>center</quote>, and
      <quote>right</quote>. 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 <quote>text-justify</quote> and
      <quote>left</quote>, <quote>center</quote> and
      <quote>right</quote> are possible states on that action. There are
      not three separate <quote>justify-left</quote>,
      <quote>justify-center</quote> and <quote>justify-right</quote>
      actions.
    </para>
    <para>
      The final common type of action is a stateless action with a
      parameter. This is typically used for actions like
      <quote>open-bookmark</quote> 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 alphanumeric, plus <quote>-</quote> and
      <quote>.</quote>) then you can use a detailed action name of the
      form <quote>justify::left</quote> 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
      <quote>action-name(5)</quote>, where the <quote>5</quote> 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
      <quote>open-bookmark(<quote>http://gnome.org/</quote>)</quote>.
    </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>
  </sect1>
  <sect1>
    <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
      <quote>fullscreen</quote> and <quote>close</quote>, or in the case
      that a window contains a document, <quote>save</quote> and
      <quote>print</quote>.
    </para>
    <para>
      Actions that impact the application as a whole rather than one
      specific window are scoped to the application. These are actions
      like <quote>about</quote> and <quote>preferences</quote>.
    </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 <quote>fullscreen</quote> 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>
  </sect1>
  <sect1>
    <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 <quote>app.</quote> for the actions with
      application scope or <quote>win.</quote> for those with window
      scope.
    </para>
    <para>
      When referring to actions on a GActionMap only the name of the
      action itself is used (ie: <quote>quit</quote>, not
      <quote>app.quit</quote>). The <quote>app.quit</quote> 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>
  </sect1>
  <sect1>
    <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>
      A typical use of GMenu inside GTK is to set up an application
      menubar with <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>
  </sect1>
  <sect1>
    <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>
  </sect1>
  <sect1>
    <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.
    </para>
    <variablelist spacing="compact">
      <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>
            Operate on colors in a <link linkend="GtkColorChooserWidget"><type>GtkColorChooserWidget</type></link>. These actions
            are
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      unusual in that they have the non-trivial parameter type (dddd):
    </para>
  </sect1>
</chapter>
