1/* gtkscrollable.c
2 * Copyright (C) 2008 Tadej Borovšak <tadeboro@gmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/**
19 * GtkScrollable:
20 *
21 * `GtkScrollable` is an interface for widgets with native scrolling ability.
22 *
23 * To implement this interface you should override the
24 * [property@Gtk.Scrollable:hadjustment] and
25 * [property@Gtk.Scrollable:vadjustment] properties.
26 *
27 * ## Creating a scrollable widget
28 *
29 * All scrollable widgets should do the following.
30 *
31 * - When a parent widget sets the scrollable child widget’s adjustments,
32 * the widget should connect to the [signal@Gtk.Adjustment::value-changed]
33 * signal. The child widget should then populate the adjustments’ properties
34 * as soon as possible, which usually means queueing an allocation right away
35 * and populating the properties in the [vfunc@Gtk.Widget.size_allocate]
36 * implementation.
37 *
38 * - Because its preferred size is the size for a fully expanded widget,
39 * the scrollable widget must be able to cope with underallocations.
40 * This means that it must accept any value passed to its
41 * [vfunc@Gtk.Widget.size_allocate] implementation.
42 *
43 * - When the parent allocates space to the scrollable child widget,
44 * the widget must ensure the adjustments’ property values are correct and up
45 * to date, for example using [method@Gtk.Adjustment.configure].
46 *
47 * - When any of the adjustments emits the [signal@Gtk.Adjustment::value-changed]
48 * signal, the scrollable widget should scroll its contents.
49 */
50
51#include "config.h"
52
53#include "gtkscrollable.h"
54
55#include "gtkadjustment.h"
56#include "gtkprivate.h"
57#include "gtktypebuiltins.h"
58#include "gtkintl.h"
59
60G_DEFINE_INTERFACE (GtkScrollable, gtk_scrollable, G_TYPE_OBJECT)
61
62static void
63gtk_scrollable_default_init (GtkScrollableInterface *iface)
64{
65 GParamSpec *pspec;
66
67 /**
68 * GtkScrollable:hadjustment: (attributes org.gtk.Property.get=gtk_scrollable_get_hadjustment org.gtk.Property.set=gtk_scrollable_set_hadjustment)
69 *
70 * Horizontal `GtkAdjustment` of the scrollable widget.
71 *
72 * This adjustment is shared between the scrollable widget and its parent.
73 */
74 pspec = g_param_spec_object (name: "hadjustment",
75 P_("Horizontal adjustment"),
76 P_("Horizontal adjustment that is shared "
77 "between the scrollable widget and its "
78 "controller"),
79 GTK_TYPE_ADJUSTMENT,
80 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT);
81 g_object_interface_install_property (g_iface: iface, pspec);
82
83 /**
84 * GtkScrollable:vadjustment: (attributes org.gtk.Property.get=gtk_scrollable_get_vadjustment org.gtk.Property.set=gtk_scrollable_set_vadjustment)
85 *
86 * Vertical `GtkAdjustment` of the scrollable widget.
87 *
88 * This adjustment is shared between the scrollable widget and its parent.
89 */
90 pspec = g_param_spec_object (name: "vadjustment",
91 P_("Vertical adjustment"),
92 P_("Vertical adjustment that is shared "
93 "between the scrollable widget and its "
94 "controller"),
95 GTK_TYPE_ADJUSTMENT,
96 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT);
97 g_object_interface_install_property (g_iface: iface, pspec);
98
99 /**
100 * GtkScrollable:hscroll-policy: (attributes org.gtk.Property.get=gtk_scrollable_get_hscroll_policy org.gtk.Property.set=gtk_scrollable_set_hscroll_policy)
101 *
102 * Determines when horizontal scrolling should start.
103 */
104 pspec = g_param_spec_enum (name: "hscroll-policy",
105 P_("Horizontal Scrollable Policy"),
106 P_("How the size of the content should be determined"),
107 enum_type: GTK_TYPE_SCROLLABLE_POLICY,
108 default_value: GTK_SCROLL_MINIMUM,
109 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
110 g_object_interface_install_property (g_iface: iface, pspec);
111
112 /**
113 * GtkScrollable:vscroll-policy: (attributes org.gtk.Property.get=gtk_scrollable_get_vscroll_policy org.gtk.Property.set=gtk_scrollable_set_vscroll_policy)
114 *
115 * Determines when vertical scrolling should start.
116 */
117 pspec = g_param_spec_enum (name: "vscroll-policy",
118 P_("Vertical Scrollable Policy"),
119 P_("How the size of the content should be determined"),
120 enum_type: GTK_TYPE_SCROLLABLE_POLICY,
121 default_value: GTK_SCROLL_MINIMUM,
122 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
123 g_object_interface_install_property (g_iface: iface, pspec);
124}
125
126/**
127 * gtk_scrollable_get_hadjustment: (attributes org.gtk.Method.get_property=hadjustment)
128 * @scrollable: a `GtkScrollable`
129 *
130 * Retrieves the `GtkAdjustment` used for horizontal scrolling.
131 *
132 * Returns: (transfer none) (nullable): horizontal `GtkAdjustment`.
133 */
134GtkAdjustment *
135gtk_scrollable_get_hadjustment (GtkScrollable *scrollable)
136{
137 GtkAdjustment *adj = NULL;
138
139 g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), NULL);
140
141 g_object_get (object: scrollable, first_property_name: "hadjustment", &adj, NULL);
142
143 /* Horrid hack; g_object_get() returns a new reference but
144 * that contradicts the memory management conventions
145 * for accessors.
146 */
147 if (adj)
148 g_object_unref (object: adj);
149
150 return adj;
151}
152
153/**
154 * gtk_scrollable_set_hadjustment: (attributes org.gtk.Method.set_property=hadjustment)
155 * @scrollable: a `GtkScrollable`
156 * @hadjustment: (nullable): a `GtkAdjustment`
157 *
158 * Sets the horizontal adjustment of the `GtkScrollable`.
159 */
160void
161gtk_scrollable_set_hadjustment (GtkScrollable *scrollable,
162 GtkAdjustment *hadjustment)
163{
164 g_return_if_fail (GTK_IS_SCROLLABLE (scrollable));
165 g_return_if_fail (hadjustment == NULL || GTK_IS_ADJUSTMENT (hadjustment));
166
167 g_object_set (object: scrollable, first_property_name: "hadjustment", hadjustment, NULL);
168}
169
170/**
171 * gtk_scrollable_get_vadjustment: (attributes org.gtk.Method.get_property=vadjustment)
172 * @scrollable: a `GtkScrollable`
173 *
174 * Retrieves the `GtkAdjustment` used for vertical scrolling.
175 *
176 * Returns: (transfer none) (nullable): vertical `GtkAdjustment`.
177 */
178GtkAdjustment *
179gtk_scrollable_get_vadjustment (GtkScrollable *scrollable)
180{
181 GtkAdjustment *adj = NULL;
182
183 g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), NULL);
184
185 g_object_get (object: scrollable, first_property_name: "vadjustment", &adj, NULL);
186
187 /* Horrid hack; g_object_get() returns a new reference but
188 * that contradicts the memory management conventions
189 * for accessors.
190 */
191 if (adj)
192 g_object_unref (object: adj);
193
194 return adj;
195}
196
197/**
198 * gtk_scrollable_set_vadjustment: (attributes org.gtk.Method.set_property=vadjustment)
199 * @scrollable: a `GtkScrollable`
200 * @vadjustment: (nullable): a `GtkAdjustment`
201 *
202 * Sets the vertical adjustment of the `GtkScrollable`.
203 */
204void
205gtk_scrollable_set_vadjustment (GtkScrollable *scrollable,
206 GtkAdjustment *vadjustment)
207{
208 g_return_if_fail (GTK_IS_SCROLLABLE (scrollable));
209 g_return_if_fail (vadjustment == NULL || GTK_IS_ADJUSTMENT (vadjustment));
210
211 g_object_set (object: scrollable, first_property_name: "vadjustment", vadjustment, NULL);
212}
213
214
215/**
216 * gtk_scrollable_get_hscroll_policy: (attributes org.gtk.Method.get_property=hscroll-policy)
217 * @scrollable: a `GtkScrollable`
218 *
219 * Gets the horizontal `GtkScrollablePolicy`.
220 *
221 * Returns: The horizontal `GtkScrollablePolicy`.
222 */
223GtkScrollablePolicy
224gtk_scrollable_get_hscroll_policy (GtkScrollable *scrollable)
225{
226 GtkScrollablePolicy policy;
227
228 g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), GTK_SCROLL_MINIMUM);
229
230 g_object_get (object: scrollable, first_property_name: "hscroll-policy", &policy, NULL);
231
232 return policy;
233}
234
235/**
236 * gtk_scrollable_set_hscroll_policy: (attributes org.gtk.Method.set_property=hscroll-policy)
237 * @scrollable: a `GtkScrollable`
238 * @policy: the horizontal `GtkScrollablePolicy`
239 *
240 * Sets the `GtkScrollablePolicy`.
241 *
242 * The policy determines whether horizontal scrolling should start
243 * below the minimum width or below the natural width.
244 */
245void
246gtk_scrollable_set_hscroll_policy (GtkScrollable *scrollable,
247 GtkScrollablePolicy policy)
248{
249 g_return_if_fail (GTK_IS_SCROLLABLE (scrollable));
250
251 g_object_set (object: scrollable, first_property_name: "hscroll-policy", policy, NULL);
252}
253
254/**
255 * gtk_scrollable_get_vscroll_policy: (attributes org.gtk.Method.get_property=vscroll-policy)
256 * @scrollable: a `GtkScrollable`
257 *
258 * Gets the vertical `GtkScrollablePolicy`.
259 *
260 * Returns: The vertical `GtkScrollablePolicy`.
261 */
262GtkScrollablePolicy
263gtk_scrollable_get_vscroll_policy (GtkScrollable *scrollable)
264{
265 GtkScrollablePolicy policy;
266
267 g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), GTK_SCROLL_MINIMUM);
268
269 g_object_get (object: scrollable, first_property_name: "vscroll-policy", &policy, NULL);
270
271 return policy;
272}
273
274/**
275 * gtk_scrollable_set_vscroll_policy: (attributes org.gtk.Method.set_property=vscroll-policy)
276 * @scrollable: a `GtkScrollable`
277 * @policy: the vertical `GtkScrollablePolicy`
278 *
279 * Sets the `GtkScrollablePolicy`.
280 *
281 * The policy determines whether vertical scrolling should start
282 * below the minimum height or below the natural height.
283 */
284void
285gtk_scrollable_set_vscroll_policy (GtkScrollable *scrollable,
286 GtkScrollablePolicy policy)
287{
288 g_return_if_fail (GTK_IS_SCROLLABLE (scrollable));
289
290 g_object_set (object: scrollable, first_property_name: "vscroll-policy", policy, NULL);
291}
292
293/**
294 * gtk_scrollable_get_border:
295 * @scrollable: a `GtkScrollable`
296 * @border: (out caller-allocates): return location for the results
297 *
298 * Returns the size of a non-scrolling border around the
299 * outside of the scrollable.
300 *
301 * An example for this would be treeview headers. GTK can use
302 * this information to display overlaid graphics, like the
303 * overshoot indication, at the right position.
304 *
305 * Returns: %TRUE if @border has been set
306 */
307gboolean
308gtk_scrollable_get_border (GtkScrollable *scrollable,
309 GtkBorder *border)
310{
311 g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), FALSE);
312 g_return_val_if_fail (border != NULL, FALSE);
313
314 if (GTK_SCROLLABLE_GET_IFACE (scrollable)->get_border)
315 return GTK_SCROLLABLE_GET_IFACE (scrollable)->get_border (scrollable, border);
316
317 return FALSE;
318}
319

source code of gtk/gtk/gtkscrollable.c