<sect1 id="ListWidget">
  <title>List Widget Overview</title>
  <para>
    GTK provides powerful widgets to display and edit lists of data.
    This document gives an overview over the concepts and how they work
    together to allow developers to implement lists.
  </para>
  <para>
    Lists are intended to be used whenever developers want to display
    many objects in roughly the same way.
  </para>
  <para>
    Lists are perfectly fine to be used for very short list of only 2 or
    3 elements, but generally scale fine to millions of items. Of
    course, the larger the list grows, the more care needs to be taken
    to choose the right data structures to keep things running well.
  </para>
  <para>
    Lists are meant to be used with changing data, both with the items
    itself changing as well as the list adding and removing items. Of
    course, they work just as well with static data.
  </para>
  <sect2>
    <title>Terminology</title>
    <para>
      These terms are used throughout the documentation when talking
      about lists and you should be aware of what they refer to. These
      are often generic terms that have a specific meaning in this
      context.
    </para>
    <para>
      <emphasis role="strong"><emphasis>Views</emphasis></emphasis> or
      <emphasis role="strong"><emphasis>list
      widgets</emphasis></emphasis> are the widgets that hold and manage
      the lists. Examples of these widgets would be <link linkend="GtkListView"><type>GtkListView</type></link> or
      <link linkend="GtkGridView"><type>GtkGridView</type></link>.
    </para>
    <para>
      Views display data from a
      <emphasis role="strong"><emphasis>model</emphasis></emphasis>. A
      model is a <link linkend="GListModel"><type>GListModel</type></link> and models can be provided in 3 ways or
      combinations thereof:
    </para>
    <itemizedlist>
      <listitem>
        <para>
          Many list models implementations already exist. There are
          models that provide specific data, like <link linkend="GtkDirectoryList"><type>GtkDirectoryList</type></link>. And
          there are models like <link linkend="GListStore"><type>GListStore</type></link> that allow building lists
          manually.
        </para>
      </listitem>
      <listitem>
        <para>
          Wrapping list models like <link linkend="GtkFilterListModel"><type>GtkFilterListModel</type></link> or
          <link linkend="GtkSortListModel"><type>GtkSortListModel</type></link> modify, adapt or combine other models.
        </para>
      </listitem>
      <listitem>
        <para>
          Last but not least, developers are encouraged to create their
          own <link linkend="GListModel"><type>GListModel</type></link> implementations. The interface is kept
          deliberately small to make this easy.
        </para>
      </listitem>
    </itemizedlist>
    <para>
      The same model can be used in multiple different views and wrapped
      with multiple different models at once.
    </para>
    <para>
      The elements in a model are called
      <emphasis role="strong"><emphasis>items</emphasis></emphasis>. All
      items are <link linkend="GObjects"><type>GObjects</type></link>.
    </para>
    <para>
      Every item in a model has a
      <emphasis role="strong"><emphasis>position</emphasis></emphasis>
      which is the unsigned integer that describes where in the model
      the item is located. The first item in a model is at position 0.
      The position of an item can of course change as other items are
      added or removed from the model.
    </para>
    <para>
      It is important to be aware of the difference between items and
      positions because the mapping from position to item is not
      permanent, so developers should think about whether they want to
      track items or positions when working with models. Oftentimes some
      things are really hard to do one way but very easy the other way.
    </para>
    <para>
      The other important part of a view is a
      <emphasis role="strong"><emphasis>factory</emphasis></emphasis>.
      Each factory is a <link linkend="GtkListItemFactory"><type>GtkListItemFactory</type></link> implementation that takes
      care of mapping the items of the model to widgets that can be
      shown in the view.
    </para>
    <para>
      The way factories do this is by creating a
      <emphasis role="strong"><emphasis>listitem</emphasis></emphasis>
      for each item that is currently in use. Listitems are always
      <link linkend="GtkListItem"><type>GtkListItem</type></link> objects. They are only ever created by GTK and
      provide information about what item they are meant to display.
    </para>
    <para>
      Different factory implementations use various different methods to
      allow developers to add the right widgets to listitems and to link
      those widgets with the item managed by the listitem. Finding a
      suitable factory implementation for the data displayed, the
      programming language and development environment is an important
      task that can simplify setting up the view tremendously.
    </para>
    <para>
      Views support selections via a
      <emphasis role="strong"><emphasis>selection
      model</emphasis></emphasis>. A selection model is an
      implementation of the <link linkend="GtkSelectionModel"><type>GtkSelectionModel</type></link> interface on top of the
      <link linkend="GListModel"><type>GListModel</type></link> interface that allows marking each item in a model as
      either selected or not selected. Just like regular models, this
      can be implemented either by implementing <link linkend="GtkSelectionModel"><type>GtkSelectionModel</type></link>
      directly or by wrapping a model with one of the GTK models
      provided for this purposes, such as <link linkend="GtkNoSelection"><type>GtkNoSelection</type></link> or
      <link linkend="GtkSingleSelection"><type>GtkSingleSelection</type></link>.
    </para>
    <para>
      The behavior of selection models - ie which items they allow
      selecting and what effect this has on other items - is completely
      up to the selection model. As such, single-selections,
      multi-selections or sharing selection state between different
      selection models and/or views is possible. The selection state of
      an item is exposed in the listitem via the <link linkend="GtkListItem--selected"><type>“selected”</type></link>
      property.
    </para>
    <para>
      Views and listitems also support activation. Activation means that
      double clicking or pressing enter while inside a focused row will
      cause the view to emit and activation signal such as
      <link linkend="GtkListView-activate"><type>“activate”</type></link>. This provides an easy way to set up lists,
      but can also be turned off on listitems if undesired.
    </para>
    <para>
      Both selections and activation are supported among other things
      via widget <link linkend="actions-overview">actions</link>. This
      allows developers to add widgets to their lists that cause
      selections to change or to trigger activation via the
      <link linkend="GtkActionable"><type>GtkActionable</type></link> interface. For a list of all supported actions see
      the relevant documentation.
    </para>
  </sect2>
  <sect2>
    <title>Behind the scenes</title>
    <para>
      While for short lists it is not a problem to instantiate widgets
      for every item in the model, once lists grow to thousands or
      millions of elements, this gets less feasible. Because of this,
      the views only create a limited amount of listitems and recycle
      them by binding them to new items. In general, views try to keep
      listitems available only for the items that can actually be seen
      on screen.
    </para>
    <para>
      While this behavior allows views to scale effortlessly to huge
      lists, it has a few implication on what can be done with views.
      For example, it is not possible to query a view for a listitem
      used for a certain position - there might not be one and even if
      there is, that listitem might soon be recycled for a new position.
    </para>
    <para>
      It is also important that developers save state they care about in
      the item and do not rely on the widgets they created as those
      widgets can be recycled for a new position at any time causing any
      state to be lost.
    </para>
    <para>
      Another important requirement for views is that they need to know
      which items are not visible so they can be recycled. Views achieve
      that by implementing the <link linkend="GtkScrollable"><type>GtkScrollable</type></link> interface and expecting to
      be placed directly into a <link linkend="GtkScrolledWindow"><type>GtkScrolledWindow</type></link>.
    </para>
    <para>
      Of course, if you are only using models with few items, this is
      not important and you can treat views like any other widget. But
      if you use large lists and your performance suffers, you should be
      aware of this. Views also allow tuning the number of listitems
      they create such as with <link linkend="gtk-grid-view-set-max-columns"><function>gtk_grid_view_set_max_columns()</function></link>, and
      developers running into performance problems should definitely
      study the tradeoffs of those and experiment with them.
    </para>
  </sect2>
  <sect2 id="model-choosing">
    <title>Choosing the right model</title>
    <para>
      GTK offers a wide variety of wrapping models which change or
      supplement an existing model (or models) in some way. But when it
      comes to storing your actual data, there are only a few ready-made
      choices available: <link linkend="GListStore"><type>GListStore</type></link> and <link linkend="GtkStringList"><type>GtkStringList</type></link>.
    </para>
    <para>
      GListStore is backed by a balanced tree and has performance
      characteristics that are expected for that data structure. It
      works reasonably well for dataset sizes in the 1,000,000 range,
      and can handle insertions and deletions. It uses a cached iter to
      make linear access to the items fast.
    </para>
    <para>
      GtkStringList is not a general store - it can only handle strings.
      It is backed by an dynamically allocated array and has performance
      characteristics that are expected for that data structure.
      GtkStringList is a good fit for any place where you would
      otherwise use <literal>char*[]</literal> and works best if the
      dataset is not very dynamic.
    </para>
    <para>
      If these models don’t fit your use case or scalability
      requirements, you should make a custom <link linkend="GListModel"><type>GListModel</type></link>. It is a small
      interface and not very hard to implement.
    </para>
    <para>
      For asymptotic performance comparisons between tree- and
      array-based implementations, see this
      <ulink url="https://en.wikipedia.org/wiki/Dynamic_array#Performance">article</ulink>.
    </para>
  </sect2>
  <sect2 id="displaying-trees">
    <title>Displaying trees</title>
    <para>
      While <link linkend="GtkTreeView"><type>GtkTreeView</type></link> provided built-in support for trees, the list
      widgets, and in particular <link linkend="GListModel"><type>GListModel</type></link> do not. This was a design
      choice because the common use case is displaying lists and not
      trees and it greatly simplifies the API interface provided.
    </para>
    <para>
      However, GTK provides functionality to make trees look and behave
      like lists for the people who still want to display lists. This is
      achieved by using the <link linkend="GtkTreeListModel"><type>GtkTreeListModel</type></link> model to flatten a tree
      into a list. The <link linkend="GtkTreeExpander"><type>GtkTreeExpander</type></link> widget can then be used inside a
      listitem to allow users to expand and collapse rows and provide a
      similar experience to <link linkend="GtkTreeView"><type>GtkTreeView</type></link>.
    </para>
    <para>
      Developers should refer to those objects’ API reference for more
      discussion on the topic.
    </para>
  </sect2>
  <sect2 id="list-styles">
    <title>List styles</title>
    <para>
      One of the advantages of the new list widgets over <link linkend="GtkTreeViews"><type>GtkTreeViews</type></link>
      and cell renderers is that they are fully themable using GTK CSS.
      This provides a lot of flexibility. The themes that ship with GTK
      provide a few predefined list styles that can be used in many
      situations:
    </para>
    <figure>
      <title>Rich list</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="rich-list.png" />
        </imageobject>
        <textobject><phrase>Rich list</phrase></textobject>
      </mediaobject>
    </figure>
    <para>
      This style of list is low density, spacious and uses an outline
      focus ring. It is suitable for lists of controls, e.g. in
      preference dialogs or settings panels. Use the .rich-list style
      class.
    </para>
    <figure>
      <title>Navigation sidebar</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="navigation-sidebar.png" />
        </imageobject>
        <textobject><phrase>Navigation sidebar</phrase></textobject>
      </mediaobject>
    </figure>
    <para>
      This style of list is medium density, using a full background to
      indicate focus and selection. Use the .navigation-sidebar style
      class.
    </para>
    <figure>
      <title>Data table</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="data-table.png" />
        </imageobject>
        <textobject><phrase>Data table</phrase></textobject>
      </mediaobject>
    </figure>
    <para>
      This style of list is a high density table, similar in style to a
      traditional treeview. Individual cells can be selectable and
      editable. Use the .data-table style class.
    </para>
  </sect2>
  <sect2>
    <title>Comparison to GtkTreeView</title>
    <para>
      Developers familiar with <link linkend="GtkTreeView"><type>GtkTreeView</type></link> may wonder how this way of
      doing lists compares to the way they know. This section will try
      to outline the similarities and differences between the two.
    </para>
    <para>
      This new approach tries to provide roughly the same functionality
      as the old approach but often uses a very different approach to
      achieve these goals.
    </para>
    <para>
      The main difference and one of the primary reasons for this new
      development is that items can be displayed using regular widgets
      and <link linkend="GtkCellRenderer"><type>GtkCellRenderer</type></link> is no longer necessary. This allows all
      benefits that widgets provide, such as complex layout and
      animating widgets and not only makes cell renderers obsolete, but
      also <link linkend="GtkCellArea"><type>GtkCellArea</type></link>.
    </para>
    <para>
      The other big difference is the massive change to the data model.
      <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link> was a rather complex interface for a tree data
      structure and <link linkend="GListModel"><type>GListModel</type></link> was deliberately designed to be a simple
      data structure for lists only. (See
      <link linkend="displaying-trees">above</link>) for how to still do
      trees with this new model.) Another big change is that the new
      model allows for bulk changes via the <link linkend="GListModel--items-changed"><type>“items-changed”</type></link>
      signal while <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link> only allows a single item to change at
      once. The goal here is of course to encourage implementation of
      custom list models.
    </para>
    <para>
      Another consequence of the new model is that it is now easily
      possible to refer to the contents of a row in the model directly
      by keeping the item, while <link linkend="GtkTreeRowReference"><type>GtkTreeRowReference</type></link> was a very slow
      mechanism to achieve the same. And because the items are real
      objects, developers can make them emit change signals causing
      listitems and their children to update, which wasn’t possible with
      <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link>.
    </para>
    <para>
      The selection handling is also different. While selections used to
      be managed via custom code in each widget, selection state is now
      meant to be managed by the selection models. In particular this
      allows for complex use cases with specialized requirements.
    </para>
    <para>
      Finally here’s a quick list of equivalent functionality to look
      for when transitioning code for easy lookup:
    </para>
    <informaltable>
      <tgroup cols="2">
        <colspec align="left" />
        <colspec align="left" />
        <thead>
          <row>
            <entry>
              Old
            </entry>
            <entry>
              New
            </entry>
          </row>
        </thead>
        <tbody>
          <row>
            <entry>
              <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link>
            </entry>
            <entry>
              <link linkend="GListModel"><type>GListModel</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreePath"><type>GtkTreePath</type></link>
            </entry>
            <entry>
              <link linkend="guint"><type>guint</type></link> position, <link linkend="GtkTreeListRow"><type>GtkTreeListRow</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeIter"><type>GtkTreeIter</type></link>
            </entry>
            <entry>
              <link linkend="guint"><type>guint</type></link> position
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeRowReference"><type>GtkTreeRowReference</type></link>
            </entry>
            <entry>
              <link linkend="GObject"><type>GObject</type></link> item
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkListStore"><type>GtkListStore</type></link>
            </entry>
            <entry>
              <link linkend="GListStore"><type>GListStore</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeStore"><type>GtkTreeStore</type></link>
            </entry>
            <entry>
              <link linkend="GtkTreeListModel"><type>GtkTreeListModel</type></link>, <link linkend="GtkTreeExpander"><type>GtkTreeExpander</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeSelection"><type>GtkTreeSelection</type></link>
            </entry>
            <entry>
              <link linkend="GtkSelectionModel"><type>GtkSelectionModel</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeViewColumn"><type>GtkTreeViewColumn</type></link>
            </entry>
            <entry>
              <link linkend="GtkColumnView"><type>GtkColumnView</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeView"><type>GtkTreeView</type></link>
            </entry>
            <entry>
              <link linkend="GtkListView"><type>GtkListView</type></link>, <link linkend="GtkColumnView"><type>GtkColumnView</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkCellView"><type>GtkCellView</type></link>
            </entry>
            <entry>
              <link linkend="GtkListItemWidget"><type>GtkListItemWidget</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkComboBox"><type>GtkComboBox</type></link>
            </entry>
            <entry>
              <link linkend="GtkDropDown"><type>GtkDropDown</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkIconView"><type>GtkIconView</type></link>
            </entry>
            <entry>
              <link linkend="GtkGridView"><type>GtkGridView</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeSortable"><type>GtkTreeSortable</type></link>
            </entry>
            <entry>
              <link linkend="GtkColumnView"><type>GtkColumnView</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeModelSort"><type>GtkTreeModelSort</type></link>
            </entry>
            <entry>
              <link linkend="GtkSortListModel"><type>GtkSortListModel</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkTreeModelFilter"><type>GtkTreeModelFilter</type></link>
            </entry>
            <entry>
              <link linkend="GtkFilterListModel"><type>GtkFilterListModel</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkCellLayout"><type>GtkCellLayout</type></link>
            </entry>
            <entry>
              <link linkend="GtkListItemFactory"><type>GtkListItemFactory</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkCellArea"><type>GtkCellArea</type></link>
            </entry>
            <entry>
              <link linkend="GtkWidget"><type>GtkWidget</type></link>
            </entry>
          </row>
          <row>
            <entry>
              <link linkend="GtkCellRenderer"><type>GtkCellRenderer</type></link>
            </entry>
            <entry>
              <link linkend="GtkWidget"><type>GtkWidget</type></link>
            </entry>
          </row>
        </tbody>
      </tgroup>
    </informaltable>
  </sect2>
</sect1>
