1Title: List Widget Overview
2Slug: gtk-list-widget
3
4GTK provides powerful widgets to display and edit lists of data. This document
5gives an overview over the concepts and how they work together to allow
6developers to implement lists.
7
8Lists are intended to be used whenever developers want to display many objects
9in roughly the same way.
10
11Lists are perfectly fine to be used for very short list of only 2 or 3 elements,
12but generally scale fine to millions of items. Of course, the larger the list
13grows, the more care needs to be taken to choose the right data structures to
14keep things running well.
15
16Lists are meant to be used with changing data, both with the items itself changing
17as well as the list adding and removing items. Of course, they work just as well
18with static data.
19
20## Terminology
21
22These terms are used throughout the documentation when talking about lists and
23you should be aware of what they refer to. These are often generic terms that
24have a specific meaning in this context.
25
26**_Views_** or **_list widgets_** are the widgets that hold and manage the lists.
27Examples of these widgets would be `GtkListView` or `GtkGridView`.
28
29Views display data from a **_model_**. A model is a `GListModel` and models can
30be provided in 3 ways or combinations thereof:
31
32 * Many list models implementations already exist. There are models that provide
33   specific data, like `GtkDirectoryList`. And there are models like `GListStore`
34   that allow building lists manually.
35
36 * Wrapping list models like `GtkFilterListModel` or `GtkSortListModel`
37   modify, adapt or combine other models.
38
39 * Last but not least, developers are encouraged to create their own `GListModel`
40   implementations. The interface is kept deliberately small to make this easy.
41
42The same model can be used in multiple different views and wrapped with
43multiple different models at once.
44
45The elements in a model are called **_items_**. All items are `GObjects`.
46
47Every item in a model has a **_position_** which is the unsigned integer that
48describes where in the model the item is located. The first item in a model is
49at position 0. The position of an item can of course change as other items are
50added or removed from the model.
51
52It is important to be aware of the difference between items and positions
53because the mapping from position to item is not permanent, so developers
54should think about whether they want to track items or positions when working
55with models. Oftentimes some things are really hard to do one way but very easy
56the other way.
57
58The other important part of a view is a **_factory_**. Each factory is
59a `GtkListItemFactory` implementation that takes care of mapping the items
60of the model to widgets that can be shown in the view.
61
62The way factories do this is by creating a **_listitem_** for each item that
63is currently in use. Listitems are always `GtkListItem` objects. They are only
64ever created by GTK and provide information about what item they are meant
65to display.
66
67Different factory implementations use various different methods to allow
68developers to add the right widgets to listitems and to link those widgets
69with the item managed by the listitem. Finding a suitable factory implementation
70for the data displayed, the programming language and development environment
71is an important task that can simplify setting up the view tremendously.
72
73Views support selections via a **_selection model_**. A selection model is an
74implementation of the `GtkSelectionModel` interface on top of the `GListModel`
75interface that allows marking each item in a model as either selected or not
76selected. Just like regular models, this can be implemented either by
77implementing `GtkSelectionModel` directly or by wrapping a model with one of
78the GTK models provided for this purposes, such as `GtkNoSelection`
79or `GtkSingleSelection`.
80
81The behavior of selection models - ie which items they allow selecting and
82what effect this has on other items - is completely up to the selection model.
83As such, single-selections, multi-selections or sharing selection state between
84different selection models and/or views is possible. The selection state of an
85item is exposed in the listitem via the `GtkListItem:selected` property.
86
87Views and listitems also support activation. Activation means that double
88clicking or pressing enter while inside a focused row will cause the view
89to emit and activation signal such as `GtkListView::activate`. This provides
90an easy way to set up lists, but can also be turned off on listitems if undesired.
91
92Both selections and activation are supported among other things via widget
93[actions](#actions-overview). This allows developers to add widgets to their
94lists that cause selections to change or to trigger activation via
95the `GtkActionable` interface. For a list of all supported actions see the
96relevant documentation.
97
98## Behind the scenes
99
100While for short lists it is not a problem to instantiate widgets for every
101item in the model, once lists grow to thousands or millions of elements, this
102gets less feasible. Because of this, the views only create a limited amount of
103listitems and recycle them by binding them to new items. In general, views try
104to keep listitems available only for the items that can actually be seen on screen.
105
106While this behavior allows views to scale effortlessly to huge lists, it has a
107few implication on what can be done with views. For example, it is not possible
108to query a view for a listitem used for a certain position - there might not be
109one and even if there is, that listitem might soon be recycled for a new position.
110
111It is also important that developers save state they care about in the item and
112do not rely on the widgets they created as those widgets can be recycled for a
113new position at any time causing any state to be lost.
114
115Another important requirement for views is that they need to know which items
116are not visible so they can be recycled. Views achieve that by implementing
117the `GtkScrollable` interface and expecting to be placed directly into
118a `GtkScrolledWindow`.
119
120Of course, if you are only using models with few items, this is not important
121and you can treat views like any other widget. But if you use large lists and
122your performance suffers, you should be aware of this. Views also allow tuning
123the number of listitems they create such as with gtk_grid_view_set_max_columns(),
124and developers running into performance problems should definitely study the
125tradeoffs of those and experiment with them.
126
127## Choosing the right model
128
129GTK offers a wide variety of wrapping models which change or supplement an
130existing model (or models) in some way. But when it comes to storing your
131actual data, there are only a few ready-made choices available: `GListStore`
132and `GtkStringList`.
133
134GListStore is backed by a balanced tree and has performance characteristics
135that are expected for that data structure. It works reasonably well for dataset
136sizes in the 1,000,000 range, and can handle insertions and deletions. It uses
137a cached iter to make linear access to the items fast.
138
139GtkStringList is not a general store - it can only handle strings. It is
140backed by an dynamically allocated array and has performance characteristics
141that are expected for that data structure. GtkStringList is a good fit for any
142place where you would otherwise use `char*[]` and works best if the dataset
143is not very dynamic.
144
145If these models don't fit your use case or scalability requirements, you
146should make a custom `GListModel`. It is a small interface and not very hard
147to implement.
148
149For asymptotic performance comparisons between tree- and array-based
150implementations, see this
151[article](https://en.wikipedia.org/wiki/Dynamic_array#Performance).
152
153## Displaying trees
154
155While `GtkTreeView` provided built-in support for trees, the list widgets, and
156in particular `GListModel` do not. This was a design choice because the common
157use case is displaying lists and not trees and it greatly simplifies the API
158interface provided.
159
160However, GTK provides functionality to make trees look and behave like lists
161for the people who still want to display lists. This is achieved by using
162the `GtkTreeListModel` model to flatten a tree into a list. The `GtkTreeExpander`
163widget can then be used inside a listitem to allow users to expand and collapse
164rows and provide a similar experience to `GtkTreeView`.
165
166Developers should refer to those objects' API reference for more discussion
167on the topic.
168
169## List styles
170
171One of the advantages of the new list widgets over `GtkTreeViews` and cell
172renderers is that they are fully themable using GTK CSS. This provides a
173lot of flexibility. The themes that ship with GTK provide a few predefined
174list styles that can be used in many situations:
175
176![Rich list](rich-list.png)
177
178This style of list is low density, spacious and uses an outline focus ring.
179It is suitable for lists of controls, e.g. in preference dialogs or
180settings panels. Use the .rich-list style class.
181
182![Navigation sidebar](navigation-sidebar.png)
183
184This style of list is medium density, using a full background to indicate
185focus and selection. Use the .navigation-sidebar style class.
186
187![Data table](data-table.png)
188
189This style of list is a high density table, similar in style to a traditional
190treeview. Individual cells can be selectable and editable. Use the .data-table
191style class.
192
193## Comparison to GtkTreeView
194
195Developers familiar with `GtkTreeView` may wonder how this way of doing lists
196compares to the way they know. This section will try to outline the similarities
197and differences between the two.
198
199This new approach tries to provide roughly the same functionality as the old
200approach but often uses a very different approach to achieve these goals.
201
202The main difference and one of the primary reasons for this new development is
203that items can be displayed using regular widgets and `GtkCellRenderer` is no
204longer necessary. This allows all benefits that widgets provide, such as complex
205layout and animating widgets and not only makes cell renderers obsolete, but
206also `GtkCellArea`.
207
208The other big difference is the massive change to the data model. `GtkTreeModel`
209was a rather complex interface for a tree data structure and `GListModel` was
210deliberately designed to be a simple data structure for lists only. (See
211[above](#displaying-trees)) for how to still do trees with this new model.)
212Another big change is that the new model allows for bulk changes via
213the `GListModel:items-changed` signal while `GtkTreeModel` only allows a single
214item to change at once. The goal here is of course to encourage implementation
215of custom list models.
216
217Another consequence of the new model is that it is now easily possible to
218refer to the contents of a row in the model directly by keeping the item,
219while `GtkTreeRowReference` was a very slow mechanism to achieve the same.
220And because the items are real objects, developers can make them emit change
221signals causing listitems and their children to update, which wasn't possible
222with `GtkTreeModel`.
223
224The selection handling is also different. While selections used to be managed
225via custom code in each widget, selection state is now meant to be managed by
226the selection models. In particular this allows for complex use cases with
227specialized requirements.
228
229Finally here's a quick list of equivalent functionality to look for when
230transitioning code for easy lookup:
231
232| Old                  | New                                  |
233| -------------------- | ------------------------------------ |
234| `GtkTreeModel`       | `GListModel`                         |
235| `GtkTreePath`        | `guint` position, `GtkTreeListRow`   |
236| `GtkTreeIter`        | `guint` position                     |
237| `GtkTreeRowReference`| `GObject` item                       |
238| `GtkListStore`       | `GListStore`                         |
239| `GtkTreeStore`       | `GtkTreeListModel`, `GtkTreeExpander`|
240| `GtkTreeSelection`   | `GtkSelectionModel`                  |
241| `GtkTreeViewColumn`  | `GtkColumnView`                      |
242| `GtkTreeView`        | `GtkListView`, `GtkColumnView`       |
243| `GtkCellView`        | `GtkListItemWidget`                  |
244| `GtkComboBox`        | `GtkDropDown`                        |
245| `GtkIconView`        | `GtkGridView`                        |
246| `GtkTreeSortable`    | `GtkColumnView`                      |
247| `GtkTreeModelSort`   | `GtkSortListModel`                   |
248| `GtkTreeModelFilter` | `GtkFilterListModel`                 |
249| `GtkCellLayout`      | `GtkListItemFactory`                 |
250| `GtkCellArea`        | `GtkWidget`                          |
251| `GtkCellRenderer`    | `GtkWidget`                          |
252
253